mirror of
https://github.com/django/django.git
synced 2025-07-06 02:39:12 +00:00
queryset-refactor: Merged to [6300]
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6340 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
7325fbf4ff
commit
ca33d307de
8
AUTHORS
8
AUTHORS
@ -149,6 +149,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Sung-Jin Hong <serialx.net@gmail.com>
|
||||
Richard House <Richard.House@i-logue.com>
|
||||
Robert Rock Howard <http://djangomojo.com/>
|
||||
Rob Hudson <http://rob.cogit8.org/>
|
||||
Jason Huggins <http://www.jrandolph.com/blog/>
|
||||
Hyun Mi Ae
|
||||
Tom Insam
|
||||
@ -182,6 +183,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
lakin.wecker@gmail.com
|
||||
Nick Lane <nick.lane.au@gmail.com>
|
||||
Stuart Langridge <http://www.kryogenix.org/>
|
||||
Paul Lanier <planier@google.com>
|
||||
Nicola Larosa <nico@teknico.net>
|
||||
Eugene Lazutkin <http://lazutkin.com/blog/>
|
||||
Jeong-Min Lee <falsetru@gmail.com>
|
||||
@ -195,6 +197,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Martin Maney <http://www.chipy.org/Martin_Maney>
|
||||
masonsimon+django@gmail.com
|
||||
Manuzhai
|
||||
Petr Marhoun <petr.marhoun@gmail.com>
|
||||
Petar Marić <http://www.petarmaric.com/>
|
||||
Nuno Mariz <nmariz@gmail.com>
|
||||
Marijn Vriens <marijn@metronomo.cl>
|
||||
@ -263,9 +266,11 @@ answer newbie questions, and generally made Django that much better:
|
||||
Jozko Skrablin <jozko.skrablin@gmail.com>
|
||||
SmileyChris <smileychris@gmail.com>
|
||||
smurf@smurf.noris.de
|
||||
Vsevolod Solovyov
|
||||
sopel
|
||||
Leo Soto <leo.soto@gmail.com>
|
||||
Wiliam Alves de Souza <wiliamsouza83@gmail.com>
|
||||
Bjørn Stabell <bjorn@exoweb.net>
|
||||
Georgi Stanojevski <glisha@gmail.com>
|
||||
Vasiliy Stavenko <stavenko@gmail.com>
|
||||
Thomas Steinacher <http://www.eggdrop.ch/>
|
||||
@ -282,6 +287,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Frank Tegtmeyer <fte@fte.to>
|
||||
thebjorn <bp@datakortet.no>
|
||||
Zach Thompson <zthompson47@gmail.com>
|
||||
Michael Thornhill
|
||||
Deepak Thukral <deep.thukral@gmail.com>
|
||||
tibimicu@gmax.net
|
||||
tobias@neuyork.de
|
||||
@ -295,10 +301,12 @@ answer newbie questions, and generally made Django that much better:
|
||||
Amit Upadhyay
|
||||
Geert Vanderkelen
|
||||
viestards.lists@gmail.com
|
||||
George Vilches <gav@thataddress.com>
|
||||
Vlado <vlado@labath.org>
|
||||
Milton Waddams
|
||||
wam-djangobug@wamber.net
|
||||
wangchun <yaohua2000@gmail.com>
|
||||
Filip Wasilewski <filip.wasilewski@gmail.com>
|
||||
Dan Watson <http://theidioteque.net/>
|
||||
Chris Wesseling <Chris.Wesseling@cwi.nl>
|
||||
James Wheare <django@sparemint.com>
|
||||
|
@ -112,6 +112,7 @@ class Settings(object):
|
||||
# Move the time zone info into os.environ. See ticket #2315 for why
|
||||
# we don't do this unconditionally (breaks Windows).
|
||||
os.environ['TZ'] = self.TIME_ZONE
|
||||
time.tzset()
|
||||
|
||||
def get_all_members(self):
|
||||
return dir(self)
|
||||
|
@ -51,6 +51,7 @@ LANGUAGES = (
|
||||
('fa', gettext_noop('Persian')),
|
||||
('fi', gettext_noop('Finnish')),
|
||||
('fr', gettext_noop('French')),
|
||||
('ga', gettext_noop('Gaeilge')),
|
||||
('gl', gettext_noop('Galician')),
|
||||
('hu', gettext_noop('Hungarian')),
|
||||
('he', gettext_noop('Hebrew')),
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ga/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/ga/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
3443
django/conf/locale/ga/LC_MESSAGES/django.po
Normal file
3443
django/conf/locale/ga/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ga/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/ga/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
116
django/conf/locale/ga/LC_MESSAGES/djangojs.po
Normal file
116
django/conf/locale/ga/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,116 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django 1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2007-09-14 12:33+0100\n"
|
||||
"PO-Revision-Date: 2007-09-14 14:19+0100\n"
|
||||
"Last-Translator: Michael Thornhill <michael.thornhill@gmail.com>\n"
|
||||
"Language-Team: Gaeilge <ga@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: contrib/admin/media/js/calendar.js:24
|
||||
#: contrib/admin/media/js/dateparse.js:32
|
||||
msgid "January February March April May June July August September October November December"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/calendar.js:25
|
||||
msgid "S M T W T F S"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:33
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||
#, perl-format
|
||||
msgid "Available %s"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||
msgid "Choose all"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||
msgid "Remove"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||
#, perl-format
|
||||
msgid "Chosen %s"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||
msgid "Select your choice(s) and click "
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||
msgid "Clear all"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||
msgid "Now"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||
msgid "Clock"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||
msgid "Choose a time"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||
msgid "Midnight"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||
msgid "6 a.m."
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||
msgid "Noon"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||
msgid "Calendar"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||
msgid "Yesterday"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||
msgid "Tomorrow"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||
msgid "Show"
|
||||
msgstr ""
|
||||
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||
msgid "Hide"
|
||||
msgstr ""
|
||||
|
@ -58,7 +58,7 @@ var SelectFilter = {
|
||||
quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s'), [field_name]));
|
||||
var selector_filter = quickElement('p', selector_chosen, gettext('Select your choice(s) and click '));
|
||||
selector_filter.className = 'selector-filter';
|
||||
quickElement('img', selector_filter, '', 'src', admin_media_prefix + 'img/admin/selector-add.gif', 'alt', 'Add');
|
||||
quickElement('img', selector_filter, '', 'src', admin_media_prefix + (is_stacked ? 'img/admin/selector_stacked-add.gif':'img/admin/selector-add.gif'), 'alt', 'Add');
|
||||
var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name'));
|
||||
to_box.className = 'filtered';
|
||||
var clear_all = quickElement('a', selector_chosen, gettext('Clear all'), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from");})()');
|
||||
|
@ -5,7 +5,7 @@ from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.db import models
|
||||
from django.shortcuts import render_to_response
|
||||
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
|
||||
from django.http import Http404, get_host
|
||||
from django.http import Http404
|
||||
from django.core import urlresolvers
|
||||
from django.contrib.admin import utils
|
||||
from django.contrib.sites.models import Site
|
||||
@ -29,7 +29,7 @@ def bookmarklets(request):
|
||||
# Hack! This couples this view to the URL it lives at.
|
||||
admin_root = request.path[:-len('doc/bookmarklets/')]
|
||||
return render_to_response('admin_doc/bookmarklets.html', {
|
||||
'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', get_host(request), admin_root),
|
||||
'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', request.get_host(), admin_root),
|
||||
}, context_instance=RequestContext(request))
|
||||
bookmarklets = staff_member_required(bookmarklets)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django.core import validators
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import connection, models
|
||||
from django.db.models.manager import EmptyManager
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@ -293,6 +294,11 @@ class Message(models.Model):
|
||||
class AnonymousUser(object):
|
||||
id = None
|
||||
username = ''
|
||||
is_staff = False
|
||||
is_active = True
|
||||
is_superuser = False
|
||||
_groups = EmptyManager()
|
||||
_user_permissions = EmptyManager()
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
@ -325,11 +331,11 @@ class AnonymousUser(object):
|
||||
raise NotImplementedError
|
||||
|
||||
def _get_groups(self):
|
||||
raise NotImplementedError
|
||||
return self._groups
|
||||
groups = property(_get_groups)
|
||||
|
||||
def _get_user_permissions(self):
|
||||
raise NotImplementedError
|
||||
return self._user_permissions
|
||||
user_permissions = property(_get_user_permissions)
|
||||
|
||||
def has_perm(self, perm):
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
>>> from models import User
|
||||
>>> from models import User, AnonymousUser
|
||||
>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
|
||||
>>> u.has_usable_password()
|
||||
True
|
||||
@ -16,4 +16,11 @@ False
|
||||
>>> u2 = User.objects.create_user('testuser2', 'test2@example.com')
|
||||
>>> u2.has_usable_password()
|
||||
False
|
||||
>>> a = AnonymousUser()
|
||||
>>> a.is_staff
|
||||
False
|
||||
>>> a.groups.all()
|
||||
[]
|
||||
>>> a.user_permissions.all()
|
||||
[]
|
||||
"""
|
@ -1,34 +1,43 @@
|
||||
"""
|
||||
Creates content types for all installed models.
|
||||
"""
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.dispatch import dispatcher
|
||||
from django.db.models import get_apps, get_models, signals
|
||||
from django.utils.encoding import smart_unicode
|
||||
|
||||
def create_contenttypes(app, created_models, verbosity=2):
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
def update_contenttypes(app, created_models, verbosity=2):
|
||||
"""
|
||||
Creates content types for models in the given app, removing any model
|
||||
entries that no longer have a matching model class.
|
||||
"""
|
||||
ContentType.objects.clear_cache()
|
||||
content_types = list(ContentType.objects.filter(app_label=app.__name__.split('.')[-2]))
|
||||
app_models = get_models(app)
|
||||
if not app_models:
|
||||
return
|
||||
for klass in app_models:
|
||||
opts = klass._meta
|
||||
try:
|
||||
ContentType.objects.get(app_label=opts.app_label,
|
||||
model=opts.object_name.lower())
|
||||
ct = ContentType.objects.get(app_label=opts.app_label,
|
||||
model=opts.object_name.lower())
|
||||
content_types.remove(ct)
|
||||
except ContentType.DoesNotExist:
|
||||
ct = ContentType(name=smart_unicode(opts.verbose_name_raw),
|
||||
app_label=opts.app_label, model=opts.object_name.lower())
|
||||
ct.save()
|
||||
if verbosity >= 2:
|
||||
print "Adding content type '%s | %s'" % (ct.app_label, ct.model)
|
||||
# The presence of any remaining content types means the supplied app has an
|
||||
# undefined model and can safely be removed, which cascades to also remove
|
||||
# related permissions.
|
||||
for ct in content_types:
|
||||
if verbosity >= 2:
|
||||
print "Deleting stale content type '%s | %s'" % (ct.app_label, ct.model)
|
||||
ct.delete()
|
||||
|
||||
def create_all_contenttypes(verbosity=2):
|
||||
def update_all_contenttypes(verbosity=2):
|
||||
for app in get_apps():
|
||||
create_contenttypes(app, None, verbosity)
|
||||
update_contenttypes(app, None, verbosity)
|
||||
|
||||
dispatcher.connect(create_contenttypes, signal=signals.post_syncdb)
|
||||
dispatcher.connect(update_contenttypes, signal=signals.post_syncdb)
|
||||
|
||||
if __name__ == "__main__":
|
||||
create_all_contenttypes()
|
||||
update_all_contenttypes()
|
||||
|
@ -25,7 +25,7 @@ class ContentTypeManager(models.Manager):
|
||||
"""
|
||||
Clear out the content-type cache. This needs to happen during database
|
||||
flushes to prevent caching of "stale" content type IDs (see
|
||||
django.contrib.contenttypes.management.create_contenttypes for where
|
||||
django.contrib.contenttypes.management.update_contenttypes for where
|
||||
this gets called).
|
||||
"""
|
||||
global CONTENT_TYPE_CACHE
|
||||
|
0
django/contrib/localflavor/pe/__init__.py
Normal file
0
django/contrib/localflavor/pe/__init__.py
Normal file
61
django/contrib/localflavor/pe/forms.py
Normal file
61
django/contrib/localflavor/pe/forms.py
Normal file
@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
PE-specific Form helpers.
|
||||
"""
|
||||
|
||||
from django.newforms import ValidationError
|
||||
from django.newforms.fields import RegexField, CharField, Select, EMPTY_VALUES
|
||||
from django.utils.translation import ugettext
|
||||
|
||||
class PEDepartmentSelect(Select):
|
||||
"""
|
||||
A Select widget that uses a list of Peruvian Departments as its choices.
|
||||
"""
|
||||
def __init__(self, attrs=None):
|
||||
from pe_department import DEPARTMENT_CHOICES
|
||||
super(PEDepartmentSelect, self).__init__(attrs, choices=DEPARTMENT_CHOICES)
|
||||
|
||||
class PEDNIField(CharField):
|
||||
"""
|
||||
A field that validates `Documento Nacional de IdentidadŽ (DNI) numbers.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PEDNIField, self).__init__(max_length=8, min_length=8, *args,
|
||||
**kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Value must be a string in the XXXXXXXX formats.
|
||||
"""
|
||||
value = super(PEDNIField, self).clean(value)
|
||||
if value in EMPTY_VALUES:
|
||||
return u''
|
||||
if not value.isdigit():
|
||||
raise ValidationError(ugettext("This field requires only numbers."))
|
||||
if len(value) != 8:
|
||||
raise ValidationError(ugettext("This field requires 8 digits."))
|
||||
|
||||
return value
|
||||
|
||||
class PERUCField(RegexField):
|
||||
"""
|
||||
This field validates a RUC (Registro Unico de Contribuyentes). A RUC is of
|
||||
the form XXXXXXXXXXX.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PERUCField, self).__init__(max_length=11, min_length=11, *args,
|
||||
**kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Value must be an 11-digit number.
|
||||
"""
|
||||
value = super(PERUCField, self).clean(value)
|
||||
if value in EMPTY_VALUES:
|
||||
return u''
|
||||
if not value.isdigit():
|
||||
raise ValidationError(ugettext("This field requires only numbers."))
|
||||
if len(value) != 11:
|
||||
raise ValidationError(ugettext("This field requires 11 digits."))
|
||||
return value
|
||||
|
35
django/contrib/localflavor/pe/pe_department.py
Normal file
35
django/contrib/localflavor/pe/pe_department.py
Normal file
@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
A list of Peru departaments as `choices` in a
|
||||
formfield.
|
||||
|
||||
This exists in this standalone file so that it's only imported into memory
|
||||
when explicitly needed.
|
||||
"""
|
||||
|
||||
DEPARTMENT_CHOICES = (
|
||||
('AMA', u'Amazonas'),
|
||||
('ANC', u'Ancash'),
|
||||
('APU', u'Apurímac'),
|
||||
('ARE', u'Arequipa'),
|
||||
('AYA', u'Ayacucho'),
|
||||
('CAJ', u'Cajamarca'),
|
||||
('CUS', u'Cusco'),
|
||||
('HUV', u'Huancavelica'),
|
||||
('HUC', u'Huánuco'),
|
||||
('ICA', u'Ica'),
|
||||
('JUN', u'Junín'),
|
||||
('LAL', u'La Libertad'),
|
||||
('LAM', u'Lambayeque'),
|
||||
('LIM', u'Lima'),
|
||||
('LOR', u'Loreto'),
|
||||
('MDD', u'Madre de Dios'),
|
||||
('MOQ', u'Moquegua'),
|
||||
('PAS', u'Pasco'),
|
||||
('PIU', u'Piura'),
|
||||
('PUN', u'Puno'),
|
||||
('SAM', u'San Martín'),
|
||||
('TAC', u'Tacna'),
|
||||
('TUM', u'Tumbes'),
|
||||
('UCA', u'Ucayali'),
|
||||
)
|
@ -15,8 +15,13 @@ class SessionManager(models.Manager):
|
||||
"Returns session key that isn't being used."
|
||||
# The random module is seeded when this Apache child is created.
|
||||
# Use SECRET_KEY as added salt.
|
||||
try:
|
||||
pid = os.getpid()
|
||||
except AttributeError:
|
||||
# No getpid() in Jython, for example
|
||||
pid = 1
|
||||
while 1:
|
||||
session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1), os.getpid(), time.time(), settings.SECRET_KEY)).hexdigest()
|
||||
session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1), pid, time.time(), settings.SECRET_KEY)).hexdigest()
|
||||
try:
|
||||
self.get(session_key=session_key)
|
||||
except self.model.DoesNotExist:
|
||||
|
@ -1,6 +1,5 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.http import get_host
|
||||
|
||||
SITE_CACHE = {}
|
||||
|
||||
@ -54,7 +53,7 @@ class RequestSite(object):
|
||||
The save() and delete() methods raise NotImplementedError.
|
||||
"""
|
||||
def __init__(self, request):
|
||||
self.domain = self.name = get_host(request)
|
||||
self.domain = self.name = request.get_host()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.domain
|
||||
|
@ -116,7 +116,7 @@ class BaseHandler(object):
|
||||
else:
|
||||
# Get the exception info now, in case another exception is thrown later.
|
||||
exc_info = sys.exc_info()
|
||||
receivers = dispatcher.send(signal=signals.got_request_exception)
|
||||
receivers = dispatcher.send(signal=signals.got_request_exception, request=request)
|
||||
# When DEBUG is False, send an error message to the admins.
|
||||
subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
|
||||
try:
|
||||
@ -142,7 +142,7 @@ def fix_location_header(request, response):
|
||||
Code constructing response objects is free to insert relative paths and
|
||||
this function converts them to absolute paths.
|
||||
"""
|
||||
if 'Location' in response and http.get_host(request):
|
||||
if 'Location' in response and request.get_host():
|
||||
response['Location'] = request.build_absolute_uri(response['Location'])
|
||||
return response
|
||||
|
||||
|
@ -50,7 +50,11 @@ def make_msgid(idstring=None):
|
||||
"""
|
||||
timeval = time.time()
|
||||
utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval))
|
||||
pid = os.getpid()
|
||||
try:
|
||||
pid = os.getpid()
|
||||
except AttributeError:
|
||||
# Not getpid() in Jython, for example.
|
||||
pid = 1
|
||||
randint = random.randrange(100000)
|
||||
if idstring is None:
|
||||
idstring = ''
|
||||
|
@ -206,7 +206,11 @@ def copy_helper(style, app_or_project, name, directory, other_name=''):
|
||||
def _make_writeable(filename):
|
||||
"Makes sure that the file is writeable. Useful if our source is read-only."
|
||||
import stat
|
||||
if sys.platform.startswith('java'):
|
||||
# On Jython there is no os.access()
|
||||
return
|
||||
if not os.access(filename, os.W_OK):
|
||||
st = os.stat(filename)
|
||||
new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
|
||||
os.chmod(filename, new_permissions)
|
||||
st = os.stat(filename)
|
||||
new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
|
||||
os.chmod(filename, new_permissions)
|
||||
|
||||
|
@ -38,16 +38,16 @@ class Command(NoArgsCommand):
|
||||
|
||||
cursor = connection.cursor()
|
||||
|
||||
# Get a list of all existing database tables,
|
||||
# so we know what needs to be added.
|
||||
table_list = table_list()
|
||||
if connection.features.uses_case_insensitive_names:
|
||||
table_name_converter = str.upper
|
||||
table_name_converter = lambda x: x.upper()
|
||||
else:
|
||||
table_name_converter = lambda x: x
|
||||
# Get a list of all existing database tables, so we know what needs to
|
||||
# be added.
|
||||
tables = [table_name_converter(name) for name in table_list()]
|
||||
|
||||
# Get a list of already installed *models* so that references work right.
|
||||
seen_models = installed_models(table_list)
|
||||
seen_models = installed_models(tables)
|
||||
created_models = set()
|
||||
pending_references = {}
|
||||
|
||||
@ -59,7 +59,7 @@ class Command(NoArgsCommand):
|
||||
# Create the model's database table, if it doesn't already exist.
|
||||
if verbosity >= 2:
|
||||
print "Processing %s.%s model" % (app_name, model._meta.object_name)
|
||||
if table_name_converter(model._meta.db_table) in table_list:
|
||||
if table_name_converter(model._meta.db_table) in tables:
|
||||
continue
|
||||
sql, references = sql_model_create(model, self.style, seen_models)
|
||||
seen_models.add(model)
|
||||
@ -71,7 +71,7 @@ class Command(NoArgsCommand):
|
||||
print "Creating table %s" % model._meta.db_table
|
||||
for statement in sql:
|
||||
cursor.execute(statement)
|
||||
table_list.append(table_name_converter(model._meta.db_table))
|
||||
tables.append(table_name_converter(model._meta.db_table))
|
||||
|
||||
# Create the m2m tables. This must be done after all tables have been created
|
||||
# to ensure that all referred tables will exist.
|
||||
|
@ -130,7 +130,7 @@ def sql_delete(app, style):
|
||||
else:
|
||||
table_names = []
|
||||
if connection.features.uses_case_insensitive_names:
|
||||
table_name_converter = str.upper
|
||||
table_name_converter = lambda x: x.upper()
|
||||
else:
|
||||
table_name_converter = lambda x: x
|
||||
|
||||
|
@ -3,9 +3,9 @@ Interfaces for serializing Django objects.
|
||||
|
||||
Usage::
|
||||
|
||||
>>> from django.core import serializers
|
||||
>>> json = serializers.serialize("json", some_query_set)
|
||||
>>> objects = list(serializers.deserialize("json", json))
|
||||
from django.core import serializers
|
||||
json = serializers.serialize("json", some_query_set)
|
||||
objects = list(serializers.deserialize("json", json))
|
||||
|
||||
To add your own serializers, use the SERIALIZATION_MODULES setting::
|
||||
|
||||
|
@ -27,13 +27,13 @@ class Serializer(base.Serializer):
|
||||
def end_object(self, obj):
|
||||
self.objects.append({
|
||||
"model" : smart_unicode(obj._meta),
|
||||
"pk" : smart_unicode(obj._get_pk_val()),
|
||||
"pk" : smart_unicode(obj._get_pk_val(), strings_only=True),
|
||||
"fields" : self._current
|
||||
})
|
||||
self._current = None
|
||||
|
||||
def handle_field(self, obj, field):
|
||||
self._current[field.name] = getattr(obj, field.name)
|
||||
self._current[field.name] = smart_unicode(getattr(obj, field.name), strings_only=True)
|
||||
|
||||
def handle_fk_field(self, obj, field):
|
||||
related = getattr(obj, field.name)
|
||||
@ -44,10 +44,11 @@ class Serializer(base.Serializer):
|
||||
else:
|
||||
# Related to remote object via other field
|
||||
related = getattr(related, field.rel.field_name)
|
||||
self._current[field.name] = related
|
||||
self._current[field.name] = smart_unicode(related, strings_only=True)
|
||||
|
||||
def handle_m2m_field(self, obj, field):
|
||||
self._current[field.name] = [related._get_pk_val() for related in getattr(obj, field.name).iterator()]
|
||||
self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True)
|
||||
for related in getattr(obj, field.name).iterator()]
|
||||
|
||||
def getvalue(self):
|
||||
return self.objects
|
||||
|
@ -405,12 +405,17 @@ class NumberIsInRange(object):
|
||||
|
||||
class IsAPowerOf(object):
|
||||
"""
|
||||
>>> v = IsAPowerOf(2)
|
||||
>>> v(4, None)
|
||||
>>> v(8, None)
|
||||
>>> v(16, None)
|
||||
>>> v(17, None)
|
||||
django.core.validators.ValidationError: ['This value must be a power of 2.']
|
||||
Usage: If you create an instance of the IsPowerOf validator:
|
||||
v = IsAPowerOf(2)
|
||||
|
||||
The following calls will succeed:
|
||||
v(4, None)
|
||||
v(8, None)
|
||||
v(16, None)
|
||||
|
||||
But this call:
|
||||
v(17, None)
|
||||
will raise "django.core.validators.ValidationError: ['This value must be a power of 2.']"
|
||||
"""
|
||||
def __init__(self, power_of):
|
||||
self.power_of = power_of
|
||||
|
@ -247,6 +247,7 @@ class Model(object):
|
||||
qn(self._meta.order_with_respect_to.column))
|
||||
cursor.execute(subsel, (getattr(self, self._meta.order_with_respect_to.attname),))
|
||||
db_values.append(cursor.fetchone()[0])
|
||||
record_exists = False
|
||||
if db_values:
|
||||
cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
|
||||
(qn(self._meta.db_table), ','.join(field_names),
|
||||
@ -261,7 +262,8 @@ class Model(object):
|
||||
transaction.commit_unless_managed()
|
||||
|
||||
# Run any post-save hooks.
|
||||
dispatcher.send(signal=signals.post_save, sender=self.__class__, instance=self)
|
||||
dispatcher.send(signal=signals.post_save, sender=self.__class__,
|
||||
instance=self, created=(not record_exists))
|
||||
|
||||
save.alters_data = True
|
||||
|
||||
|
@ -919,11 +919,21 @@ class PhoneNumberField(IntegerField):
|
||||
class PositiveIntegerField(IntegerField):
|
||||
def get_manipulator_field_objs(self):
|
||||
return [oldforms.PositiveIntegerField]
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {'min_value': 0}
|
||||
defaults.update(kwargs)
|
||||
return super(PositiveIntegerField, self).formfield(**defaults)
|
||||
|
||||
class PositiveSmallIntegerField(IntegerField):
|
||||
def get_manipulator_field_objs(self):
|
||||
return [oldforms.PositiveSmallIntegerField]
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {'min_value': 0}
|
||||
defaults.update(kwargs)
|
||||
return super(PositiveSmallIntegerField, self).formfield(**defaults)
|
||||
|
||||
class SlugField(CharField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['max_length'] = kwargs.get('max_length', 50)
|
||||
|
@ -111,3 +111,7 @@ class ManagerDescriptor(object):
|
||||
if instance != None:
|
||||
raise AttributeError, "Manager isn't accessible via %s instances" % type.__name__
|
||||
return self.manager
|
||||
|
||||
class EmptyManager(Manager):
|
||||
def get_query_set(self):
|
||||
return self.get_empty_query_set()
|
||||
|
@ -9,7 +9,6 @@ from django.utils.datastructures import DotExpandedDict
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import ugettext as _
|
||||
import types
|
||||
|
||||
def add_manipulators(sender):
|
||||
cls = sender
|
||||
@ -38,7 +37,7 @@ class ManipulatorDescriptor(object):
|
||||
bases = [self.base]
|
||||
if hasattr(model, 'Manipulator'):
|
||||
bases = [model.Manipulator] + bases
|
||||
self.man = types.ClassType(self.name, tuple(bases), {})
|
||||
self.man = type(self.name, tuple(bases), {})
|
||||
self.man._prepare(model)
|
||||
return self.man
|
||||
|
||||
|
@ -44,6 +44,20 @@ class HttpRequest(object):
|
||||
|
||||
__contains__ = has_key
|
||||
|
||||
def get_host(self):
|
||||
"Returns the HTTP host using the environment or request headers."
|
||||
# We try three options, in order of decreasing preference.
|
||||
host = self.META.get('HTTP_X_FORWARDED_HOST', '')
|
||||
if 'HTTP_HOST' in self.META:
|
||||
host = self.META['HTTP_HOST']
|
||||
else:
|
||||
# Reconstruct the host using the algorithm from PEP 333.
|
||||
host = self.META['SERVER_NAME']
|
||||
server_port = self.META['SERVER_PORT']
|
||||
if server_port != (self.is_secure() and 443 or 80):
|
||||
host = '%s:%s' % (host, server_port)
|
||||
return host
|
||||
|
||||
def get_full_path(self):
|
||||
return ''
|
||||
|
||||
@ -57,7 +71,7 @@ class HttpRequest(object):
|
||||
location = self.get_full_path()
|
||||
if not ':' in location:
|
||||
current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http',
|
||||
get_host(self), self.path)
|
||||
self.get_host(), self.path)
|
||||
location = urljoin(current_uri, location)
|
||||
return location
|
||||
|
||||
@ -381,19 +395,9 @@ class HttpResponseServerError(HttpResponse):
|
||||
def __init__(self, *args, **kwargs):
|
||||
HttpResponse.__init__(self, *args, **kwargs)
|
||||
|
||||
# A backwards compatible alias for HttpRequest.get_host.
|
||||
def get_host(request):
|
||||
"Gets the HTTP host from the environment or request headers."
|
||||
# We try three options, in order of decreasing preference.
|
||||
host = request.META.get('HTTP_X_FORWARDED_HOST', '')
|
||||
if 'HTTP_HOST' in request.META:
|
||||
host = request.META['HTTP_HOST']
|
||||
else:
|
||||
# Reconstruct the host using the algorithm from PEP 333.
|
||||
host = request.META['SERVER_NAME']
|
||||
server_port = request.META['SERVER_PORT']
|
||||
if server_port != (request.is_secure() and 443 or 80):
|
||||
host = '%s:%s' % (host, server_port)
|
||||
return host
|
||||
return request.get_host()
|
||||
|
||||
# It's neither necessary nor appropriate to use
|
||||
# django.utils.encoding.smart_unicode for parsing URLs and form inputs. Thus,
|
||||
|
@ -32,7 +32,7 @@ class CommonMiddleware(object):
|
||||
return http.HttpResponseForbidden('<h1>Forbidden</h1>')
|
||||
|
||||
# Check for a redirect based on settings.APPEND_SLASH and settings.PREPEND_WWW
|
||||
host = http.get_host(request)
|
||||
host = request.get_host()
|
||||
old_url = [host, request.path]
|
||||
new_url = old_url[:]
|
||||
if settings.PREPEND_WWW and old_url[0] and not old_url[0].startswith('www.'):
|
||||
@ -61,7 +61,7 @@ class CommonMiddleware(object):
|
||||
if settings.SEND_BROKEN_LINK_EMAILS:
|
||||
# If the referrer was from an internal link or a non-search-engine site,
|
||||
# send a note to the managers.
|
||||
domain = http.get_host(request)
|
||||
domain = request.get_host()
|
||||
referer = request.META.get('HTTP_REFERER', None)
|
||||
is_internal = _is_internal_request(domain, referer)
|
||||
path = request.get_full_path()
|
||||
|
@ -144,7 +144,7 @@ class IntegerField(Field):
|
||||
if value in EMPTY_VALUES:
|
||||
return None
|
||||
try:
|
||||
value = int(value)
|
||||
value = int(str(value))
|
||||
except (ValueError, TypeError):
|
||||
raise ValidationError(ugettext(u'Enter a whole number.'))
|
||||
if self.max_value is not None and value > self.max_value:
|
||||
@ -192,7 +192,7 @@ class DecimalField(Field):
|
||||
super(DecimalField, self).clean(value)
|
||||
if not self.required and value in EMPTY_VALUES:
|
||||
return None
|
||||
value = value.strip()
|
||||
value = str(value).strip()
|
||||
try:
|
||||
value = Decimal(value)
|
||||
except DecimalException:
|
||||
@ -452,6 +452,10 @@ class BooleanField(Field):
|
||||
def clean(self, value):
|
||||
"Returns a Python boolean object."
|
||||
super(BooleanField, self).clean(value)
|
||||
# Explicitly check for the string '0', which is what as hidden field
|
||||
# will submit for False.
|
||||
if value == '0':
|
||||
return False
|
||||
return bool(value)
|
||||
|
||||
class NullBooleanField(BooleanField):
|
||||
|
@ -212,6 +212,16 @@ class BaseForm(StrAndUnicode):
|
||||
"""
|
||||
return self.cleaned_data
|
||||
|
||||
def is_multipart(self):
|
||||
"""
|
||||
Returns True if the form needs to be multipart-encrypted, i.e. it has
|
||||
FileInput. Otherwise, False.
|
||||
"""
|
||||
for field in self.fields.values():
|
||||
if field.widget.needs_multipart_form:
|
||||
return True
|
||||
return False
|
||||
|
||||
class Form(BaseForm):
|
||||
"A collection of Fields, plus their associated data."
|
||||
# This is a separate class from BaseForm in order to abstract the way
|
||||
|
@ -1,5 +1,5 @@
|
||||
from django.utils.html import escape
|
||||
from django.utils.encoding import smart_unicode, StrAndUnicode
|
||||
from django.utils.encoding import smart_unicode, StrAndUnicode, force_unicode
|
||||
from django.utils.functional import Promise
|
||||
|
||||
def flatatt(attrs):
|
||||
@ -22,10 +22,10 @@ class ErrorDict(dict, StrAndUnicode):
|
||||
|
||||
def as_ul(self):
|
||||
if not self: return u''
|
||||
return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s%s</li>' % (k, smart_unicode(v)) for k, v in self.items()])
|
||||
return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s%s</li>' % (k, force_unicode(v)) for k, v in self.items()])
|
||||
|
||||
def as_text(self):
|
||||
return u'\n'.join([u'* %s\n%s' % (k, u'\n'.join([u' * %s' % smart_unicode(i) for i in v])) for k, v in self.items()])
|
||||
return u'\n'.join([u'* %s\n%s' % (k, u'\n'.join([u' * %s' % force_unicode(i) for i in v])) for k, v in self.items()])
|
||||
|
||||
class ErrorList(list, StrAndUnicode):
|
||||
"""
|
||||
@ -36,11 +36,11 @@ class ErrorList(list, StrAndUnicode):
|
||||
|
||||
def as_ul(self):
|
||||
if not self: return u''
|
||||
return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s</li>' % smart_unicode(e) for e in self])
|
||||
return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s</li>' % force_unicode(e) for e in self])
|
||||
|
||||
def as_text(self):
|
||||
if not self: return u''
|
||||
return u'\n'.join([u'* %s' % smart_unicode(e) for e in self])
|
||||
return u'\n'.join([u'* %s' % force_unicode(e) for e in self])
|
||||
|
||||
class ValidationError(Exception):
|
||||
def __init__(self, message):
|
||||
@ -58,3 +58,4 @@ class ValidationError(Exception):
|
||||
# AttributeError: ValidationError instance has no attribute 'args'
|
||||
# See http://www.python.org/doc/current/tut/node10.html#handling
|
||||
return repr(self.messages)
|
||||
|
||||
|
@ -24,6 +24,7 @@ __all__ = (
|
||||
|
||||
class Widget(object):
|
||||
is_hidden = False # Determines whether this corresponds to an <input type="hidden">.
|
||||
needs_multipart_form = False # Determines does this widget need multipart-encrypted form
|
||||
|
||||
def __init__(self, attrs=None):
|
||||
if attrs is not None:
|
||||
@ -120,6 +121,7 @@ class MultipleHiddenInput(HiddenInput):
|
||||
|
||||
class FileInput(Input):
|
||||
input_type = 'file'
|
||||
needs_multipart_form = True
|
||||
|
||||
def render(self, name, value, attrs=None):
|
||||
return super(FileInput, self).render(name, None, attrs=attrs)
|
||||
|
@ -16,7 +16,6 @@ def render_to_response(*args, **kwargs):
|
||||
"""
|
||||
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
|
||||
return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
|
||||
load_and_render = render_to_response # For backwards compatibility.
|
||||
|
||||
def _get_queryset(klass):
|
||||
"""
|
||||
|
@ -34,14 +34,8 @@ will be raised if the template doesn't have proper syntax.
|
||||
|
||||
Sample code:
|
||||
|
||||
>>> import template
|
||||
>>> s = '''
|
||||
... <html>
|
||||
... {% if test %}
|
||||
... <h1>{{ varvalue }}</h1>
|
||||
... {% endif %}
|
||||
... </html>
|
||||
... '''
|
||||
>>> from django import template
|
||||
>>> s = u'<html>{% if test %}<h1>{{ varvalue }}</h1>{% endif %}</html>'
|
||||
>>> t = template.Template(s)
|
||||
|
||||
(t is now a compiled template, and its render() method can be called multiple
|
||||
@ -49,10 +43,10 @@ times with multiple contexts)
|
||||
|
||||
>>> c = template.Context({'test':True, 'varvalue': 'Hello'})
|
||||
>>> t.render(c)
|
||||
'\n<html>\n\n <h1>Hello</h1>\n\n</html>\n'
|
||||
u'<html><h1>Hello</h1></html>'
|
||||
>>> c = template.Context({'test':False, 'varvalue': 'Hello'})
|
||||
>>> t.render(c)
|
||||
'\n<html>\n\n</html>\n'
|
||||
u'<html></html>'
|
||||
"""
|
||||
import re
|
||||
from inspect import getargspec
|
||||
@ -529,10 +523,11 @@ class FilterExpression(object):
|
||||
and return a list of tuples of the filter name and arguments.
|
||||
Sample:
|
||||
>>> token = 'variable|default:"Default value"|date:"Y-m-d"'
|
||||
>>> p = FilterParser(token)
|
||||
>>> p.filters
|
||||
[('default', 'Default value'), ('date', 'Y-m-d')]
|
||||
>>> p.var
|
||||
>>> p = Parser('')
|
||||
>>> fe = FilterExpression(token, p)
|
||||
>>> len(fe.filters)
|
||||
2
|
||||
>>> fe.var
|
||||
'variable'
|
||||
|
||||
This class should never be instantiated outside of the
|
||||
@ -647,7 +642,7 @@ def resolve_variable(path, context):
|
||||
|
||||
>>> c = {'article': {'section':'News'}}
|
||||
>>> resolve_variable('article.section', c)
|
||||
'News'
|
||||
u'News'
|
||||
>>> resolve_variable('article', c)
|
||||
{'section': 'News'}
|
||||
>>> class AClass: pass
|
||||
@ -655,7 +650,7 @@ def resolve_variable(path, context):
|
||||
>>> c.article = AClass()
|
||||
>>> c.article.section = 'News'
|
||||
>>> resolve_variable('article.section', c)
|
||||
'News'
|
||||
u'News'
|
||||
|
||||
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
|
||||
"""
|
||||
|
@ -795,7 +795,7 @@ def load(parser, token):
|
||||
for taglib in bits[1:]:
|
||||
# add the library to the parser
|
||||
try:
|
||||
lib = get_library("django.templatetags.%s" % taglib.split('.')[-1])
|
||||
lib = get_library("django.templatetags.%s" % taglib)
|
||||
parser.add_library(lib)
|
||||
except InvalidTemplateLibrary, e:
|
||||
raise TemplateSyntaxError, "'%s' is not a valid tag library: %s" % (taglib, e)
|
||||
|
@ -238,22 +238,20 @@ class DotExpandedDict(dict):
|
||||
may contain dots to specify inner dictionaries. It's confusing, but this
|
||||
example should make sense.
|
||||
|
||||
>>> d = DotExpandedDict({'person.1.firstname': ['Simon'],
|
||||
'person.1.lastname': ['Willison'],
|
||||
'person.2.firstname': ['Adrian'],
|
||||
>>> d = DotExpandedDict({'person.1.firstname': ['Simon'], \
|
||||
'person.1.lastname': ['Willison'], \
|
||||
'person.2.firstname': ['Adrian'], \
|
||||
'person.2.lastname': ['Holovaty']})
|
||||
>>> d
|
||||
{'person': {'1': {'lastname': ['Willison'], 'firstname': ['Simon']},
|
||||
'2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}}}
|
||||
{'person': {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}}}
|
||||
>>> d['person']
|
||||
{'1': {'firstname': ['Simon'], 'lastname': ['Willison'],
|
||||
'2': {'firstname': ['Adrian'], 'lastname': ['Holovaty']}
|
||||
{'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}}
|
||||
>>> d['person']['1']
|
||||
{'firstname': ['Simon'], 'lastname': ['Willison']}
|
||||
{'lastname': ['Willison'], 'firstname': ['Simon']}
|
||||
|
||||
# Gotcha: Results are unpredictable if the dots are "uneven":
|
||||
>>> DotExpandedDict({'c.1': 2, 'c.2': 3, 'c': 1})
|
||||
>>> {'c': 1}
|
||||
{'c': 1}
|
||||
"""
|
||||
def __init__(self, key_to_list_mapping):
|
||||
for k, v in key_to_list_mapping.items():
|
||||
|
@ -248,10 +248,15 @@ class DateFormat(TimeFormat):
|
||||
return doy
|
||||
|
||||
def Z(self):
|
||||
"""Time zone offset in seconds (i.e. '-43200' to '43200'). The offset
|
||||
for timezones west of UTC is always negative, and for those east of UTC
|
||||
is always positive."""
|
||||
return self.timezone.utcoffset(self.data).seconds
|
||||
"""
|
||||
Time zone offset in seconds (i.e. '-43200' to '43200'). The offset for
|
||||
timezones west of UTC is always negative, and for those east of UTC is
|
||||
always positive.
|
||||
"""
|
||||
offset = self.timezone.utcoffset(self.data)
|
||||
# Only days can be negative, so negative offsets have days=-1 and
|
||||
# seconds positive. Positive offsets have days=0
|
||||
return offset.days * 86400 + offset.seconds
|
||||
|
||||
def format(value, format_string):
|
||||
"Convenience function"
|
||||
|
@ -30,7 +30,7 @@ def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
|
||||
|
||||
If strings_only is True, don't convert (some) non-string-like objects.
|
||||
"""
|
||||
if strings_only and isinstance(s, (types.NoneType, int)):
|
||||
if strings_only and isinstance(s, (types.NoneType, int, long)):
|
||||
return s
|
||||
if not isinstance(s, basestring,):
|
||||
if hasattr(s, '__unicode__'):
|
||||
|
@ -3,6 +3,7 @@ Syndication feed generation library -- used for generating RSS, etc.
|
||||
|
||||
Sample usage:
|
||||
|
||||
>>> from django.utils import feedgenerator
|
||||
>>> feed = feedgenerator.Rss201rev2Feed(
|
||||
... title=u"Poynter E-Media Tidbits",
|
||||
... link=u"http://www.poynter.org/column.asp?id=31",
|
||||
|
@ -101,6 +101,13 @@ def lazy(func, *resultclasses):
|
||||
else:
|
||||
raise AssertionError('__mod__ not supported for non-string types')
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
# Instances of this class are effectively immutable. It's just a
|
||||
# collection of functions. So we don't need to do anything
|
||||
# complicated for copying.
|
||||
memo[id(self)] = self
|
||||
return self
|
||||
|
||||
def __wrapper__(*args, **kw):
|
||||
# Creates the proxy object, instead of the actual value.
|
||||
return __proxy__(args, kw)
|
||||
|
@ -491,6 +491,8 @@ def templatize(src):
|
||||
elif g[0] == "'": g = g.strip("'")
|
||||
out.write(' gettext(%r) ' % g)
|
||||
elif bmatch:
|
||||
for fmatch in constant_re.findall(t.contents):
|
||||
out.write(' _(%s) ' % fmatch)
|
||||
intrans = True
|
||||
inplural = False
|
||||
singular = []
|
||||
|
@ -2,11 +2,12 @@ from django.shortcuts import render_to_response
|
||||
from django.template import loader, RequestContext
|
||||
from django.http import HttpResponse, HttpResponsePermanentRedirect, HttpResponseGone
|
||||
|
||||
def direct_to_template(request, template, extra_context={}, mimetype=None, **kwargs):
|
||||
def direct_to_template(request, template, extra_context=None, mimetype=None, **kwargs):
|
||||
"""
|
||||
Render a given template with any extra URL parameters in the context as
|
||||
``{{ params }}``.
|
||||
"""
|
||||
if extra_context is None: extra_context = {}
|
||||
dictionary = {'params': kwargs}
|
||||
for key, value in extra_context.items():
|
||||
if callable(value):
|
||||
|
@ -244,6 +244,9 @@ Anonymous users
|
||||
the ``django.contrib.auth.models.User`` interface, with these differences:
|
||||
|
||||
* ``id`` is always ``None``.
|
||||
* ``is_staff`` and ``is_superuser`` are always False.
|
||||
* ``is_active`` is always True.
|
||||
* ``groups`` and ``user_permissions`` are always empty.
|
||||
* ``is_anonymous()`` returns ``True`` instead of ``False``.
|
||||
* ``is_authenticated()`` returns ``False`` instead of ``True``.
|
||||
* ``has_perm()`` always returns ``False``.
|
||||
@ -992,10 +995,10 @@ Writing an authentication backend
|
||||
---------------------------------
|
||||
|
||||
An authentication backend is a class that implements two methods:
|
||||
``get_user(id)`` and ``authenticate(**credentials)``.
|
||||
``get_user(user_id)`` and ``authenticate(**credentials)``.
|
||||
|
||||
The ``get_user`` method takes an ``id`` -- which could be a username, database
|
||||
ID or whatever -- and returns a ``User`` object.
|
||||
The ``get_user`` method takes a ``user_id`` -- which could be a username,
|
||||
database ID or whatever -- and returns a ``User`` object.
|
||||
|
||||
The ``authenticate`` method takes credentials as keyword arguments. Most of
|
||||
the time, it'll just look like this::
|
||||
|
@ -654,10 +654,31 @@ info, with the ``DATABASE_ENGINE`` setting. You will also need a ``ROOT_URLCONF`
|
||||
setting (its value is ignored; it just needs to be present) and a ``SITE_ID``
|
||||
setting (any non-zero integer value will do) in order for all the tests to pass.
|
||||
|
||||
The unit tests will not touch your existing databases; they create a new
|
||||
database, called ``django_test_db``, which is deleted when the tests are
|
||||
finished. This means your user account needs permission to execute ``CREATE
|
||||
DATABASE``.
|
||||
If you're using the ``sqlite3`` database backend, no further settings are
|
||||
needed. A temporary database will be created in memory when running the tests.
|
||||
|
||||
If you're using another backend:
|
||||
|
||||
* Your ``DATABASE_USER`` setting needs to specify an existing user account
|
||||
for the database engine.
|
||||
|
||||
* The ``DATABASE_NAME`` setting must be the name of an existing database to
|
||||
which the given user has permission to connect. The unit tests will not
|
||||
touch this database; the test runner creates a new database whose name is
|
||||
``DATABASE_NAME`` prefixed with ``test_``, and this test database is
|
||||
deleted when the tests are finished. This means your user account needs
|
||||
permission to execute ``CREATE DATABASE``.
|
||||
|
||||
To run a subset of the unit tests, append the names of the test modules to the
|
||||
``runtests.py`` command line. See the list of directories in
|
||||
``tests/modeltests`` and ``tests/regressiontests`` for module names.
|
||||
|
||||
As an example, if Django is not in your ``PYTHONPATH``, you placed
|
||||
``settings.py`` in the ``tests/`` directory, and you'd like to only run tests
|
||||
for generic relations and internationalization, type::
|
||||
|
||||
PYTHONPATH=..
|
||||
./runtests.py --settings=settings generic_relations i18n
|
||||
|
||||
Requesting features
|
||||
===================
|
||||
|
@ -117,7 +117,7 @@ Here's a sample configuration which uses a MySQL option file::
|
||||
[client]
|
||||
database = DATABASE_NAME
|
||||
user = DATABASE_USER
|
||||
passwd = DATABASE_PASSWORD
|
||||
password = DATABASE_PASSWORD
|
||||
default-character-set = utf8
|
||||
|
||||
Several other MySQLdb connection options may be useful, such as ``ssl``,
|
||||
|
@ -511,6 +511,9 @@ like so::
|
||||
|
||||
Entry.objects.order_by('?')
|
||||
|
||||
Note: ``order_by('?')`` queries may be expensive and slow, depending on the
|
||||
database backend you're using.
|
||||
|
||||
To order by a field in a different table, add the other table's name and a dot,
|
||||
like so::
|
||||
|
||||
|
@ -46,9 +46,8 @@ Prerequisite: flup
|
||||
==================
|
||||
|
||||
Before you can start using FastCGI with Django, you'll need to install flup_,
|
||||
which is a Python library for dealing with FastCGI. Make sure to use the latest
|
||||
Subversion snapshot of flup, as some users have reported stalled pages with
|
||||
older flup versions.
|
||||
which is a Python library for dealing with FastCGI. Version 0.5 or newer should
|
||||
work fine.
|
||||
|
||||
.. _flup: http://www.saddi.com/software/flup/
|
||||
|
||||
|
@ -699,7 +699,10 @@ A page representing a list of objects.
|
||||
displayed per page. If this is given, the view will paginate objects with
|
||||
``paginate_by`` objects per page. The view will expect either a ``page``
|
||||
query string parameter (via ``GET``) or a ``page`` variable specified in
|
||||
the URLconf. See "Notes on pagination" below.
|
||||
the URLconf. See `Notes on pagination`_ below.
|
||||
|
||||
* ``page``: The current page number, as an integer. This is 1-based.
|
||||
See `Notes on pagination`_ below.
|
||||
|
||||
* ``template_name``: The full name of a template to use in rendering the
|
||||
page. This lets you override the default template name (see below).
|
||||
@ -775,7 +778,7 @@ If the results are paginated, the context will contain these extra variables:
|
||||
page.
|
||||
|
||||
* **New in Django development version:** ``page_range``: A list of the
|
||||
page numbers that are available. This is 1-based.
|
||||
page numbers that are available. This is 1-based.
|
||||
|
||||
Notes on pagination
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
142
docs/i18n.txt
142
docs/i18n.txt
@ -27,21 +27,8 @@ Essentially, Django does two things:
|
||||
* It uses these hooks to translate Web apps for particular users according
|
||||
to their language preferences.
|
||||
|
||||
How to internationalize your app: in three steps
|
||||
------------------------------------------------
|
||||
|
||||
1. Embed translation strings in your Python code and templates.
|
||||
2. Get translations for those strings, in whichever languages you want to
|
||||
support.
|
||||
3. Activate the locale middleware in your Django settings.
|
||||
|
||||
.. admonition:: Behind the scenes
|
||||
|
||||
Django's translation machinery uses the standard ``gettext`` module that
|
||||
comes with Python.
|
||||
|
||||
If you don't need internationalization
|
||||
======================================
|
||||
If you don't need internationalization in your app
|
||||
==================================================
|
||||
|
||||
Django's internationalization hooks are on by default, and that means there's a
|
||||
bit of i18n-related overhead in certain places of the framework. If you don't
|
||||
@ -55,8 +42,21 @@ from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting.
|
||||
|
||||
.. _documentation for USE_I18N: ../settings/#use-i18n
|
||||
|
||||
How to specify translation strings
|
||||
==================================
|
||||
If you do need internationalization: three steps
|
||||
================================================
|
||||
|
||||
1. Embed translation strings in your Python code and templates.
|
||||
2. Get translations for those strings, in whichever languages you want to
|
||||
support.
|
||||
3. Activate the locale middleware in your Django settings.
|
||||
|
||||
.. admonition:: Behind the scenes
|
||||
|
||||
Django's translation machinery uses the standard ``gettext`` module that
|
||||
comes with Python.
|
||||
|
||||
1. How to specify translation strings
|
||||
=====================================
|
||||
|
||||
Translation strings specify "This text should be translated." These strings can
|
||||
appear in your Python code and templates. It's your responsibility to mark
|
||||
@ -295,7 +295,7 @@ string, so they don't need to be aware of translations.
|
||||
.. _Django templates: ../templates_python/
|
||||
|
||||
Working with lazy translation objects
|
||||
=====================================
|
||||
-------------------------------------
|
||||
|
||||
Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models
|
||||
and utility functions is a common operation. When you're working with these
|
||||
@ -305,7 +305,7 @@ convert them to strings, because they should be converted as late as possible
|
||||
couple of helper functions.
|
||||
|
||||
Joining strings: string_concat()
|
||||
--------------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Standard Python string joins (``''.join([...])``) will not work on lists
|
||||
containing lazy translation objects. Instead, you can use
|
||||
@ -324,7 +324,7 @@ strings when ``result`` itself is used in a string (usually at template
|
||||
rendering time).
|
||||
|
||||
The allow_lazy() decorator
|
||||
--------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Django offers many utility functions (particularly in ``django.utils``) that
|
||||
take a string as their first argument and do something to that string. These
|
||||
@ -359,8 +359,8 @@ Using this decorator means you can write your function and assume that the
|
||||
input is a proper string, then add support for lazy translation objects at the
|
||||
end.
|
||||
|
||||
How to create language files
|
||||
============================
|
||||
2. How to create language files
|
||||
===============================
|
||||
|
||||
Once you've tagged your strings for later translation, you need to write (or
|
||||
obtain) the language translations themselves. Here's how that works.
|
||||
@ -393,7 +393,7 @@ To create or update a message file, run this command::
|
||||
|
||||
...where ``de`` is the language code for the message file you want to create.
|
||||
The language code, in this case, is in locale format. For example, it's
|
||||
``pt_BR`` for Brazilian Portugese and ``de_AT`` for Austrian German.
|
||||
``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian German.
|
||||
|
||||
The script should be run from one of three places:
|
||||
|
||||
@ -490,8 +490,8 @@ That's it. Your translations are ready for use.
|
||||
|
||||
.. _Submitting and maintaining translations: ../contributing/
|
||||
|
||||
How Django discovers language preference
|
||||
========================================
|
||||
3. How Django discovers language preference
|
||||
===========================================
|
||||
|
||||
Once you've prepared your translations -- or, if you just want to use the
|
||||
translations that come with Django -- you'll just need to activate translation
|
||||
@ -546,7 +546,7 @@ following this algorithm:
|
||||
Notes:
|
||||
|
||||
* In each of these places, the language preference is expected to be in the
|
||||
standard language format, as a string. For example, Brazilian Portugese
|
||||
standard language format, as a string. For example, Brazilian Portuguese
|
||||
is ``pt-br``.
|
||||
* If a base language is available but the sublanguage specified is not,
|
||||
Django uses the base language. For example, if a user specifies ``de-at``
|
||||
@ -629,44 +629,6 @@ in ``request.LANGUAGE_CODE``.
|
||||
.. _session: ../sessions/
|
||||
.. _request object: ../request_response/#httprequest-objects
|
||||
|
||||
The ``set_language`` redirect view
|
||||
==================================
|
||||
|
||||
As a convenience, Django comes with a view, ``django.views.i18n.set_language``,
|
||||
that sets a user's language preference and redirects back to the previous page.
|
||||
|
||||
Activate this view by adding the following line to your URLconf::
|
||||
|
||||
(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
|
||||
(Note that this example makes the view available at ``/i18n/setlang/``.)
|
||||
|
||||
The view expects to be called via the ``GET`` method, with a ``language``
|
||||
parameter set in the query string. If session support is enabled, the view
|
||||
saves the language choice in the user's session. Otherwise, it saves the
|
||||
language choice in a ``django_language`` cookie.
|
||||
|
||||
After setting the language choice, Django redirects the user, following this
|
||||
algorithm:
|
||||
|
||||
* Django looks for a ``next`` parameter in the query string.
|
||||
* If that doesn't exist, or is empty, Django tries the URL in the
|
||||
``Referer`` header.
|
||||
* If that's empty -- say, if a user's browser suppresses that header --
|
||||
then the user will be redirected to ``/`` (the site root) as a fallback.
|
||||
|
||||
Here's example HTML template code::
|
||||
|
||||
<form action="/i18n/setlang/" method="get">
|
||||
<input name="next" type="hidden" value="/next/page/" />
|
||||
<select name="language">
|
||||
{% for lang in LANGUAGES %}
|
||||
<option value="{{ lang.0 }}">{{ lang.1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
|
||||
Using translations in your own projects
|
||||
=======================================
|
||||
|
||||
@ -728,6 +690,44 @@ The easiest way out is to store applications that are not part of the project
|
||||
connected to your explicit project and not strings that are distributed
|
||||
independently.
|
||||
|
||||
The ``set_language`` redirect view
|
||||
==================================
|
||||
|
||||
As a convenience, Django comes with a view, ``django.views.i18n.set_language``,
|
||||
that sets a user's language preference and redirects back to the previous page.
|
||||
|
||||
Activate this view by adding the following line to your URLconf::
|
||||
|
||||
(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
|
||||
(Note that this example makes the view available at ``/i18n/setlang/``.)
|
||||
|
||||
The view expects to be called via the ``POST`` method, with a ``language``
|
||||
parameter set in request. If session support is enabled, the view
|
||||
saves the language choice in the user's session. Otherwise, it saves the
|
||||
language choice in a ``django_language`` cookie.
|
||||
|
||||
After setting the language choice, Django redirects the user, following this
|
||||
algorithm:
|
||||
|
||||
* Django looks for a ``next`` parameter in ``POST`` request.
|
||||
* If that doesn't exist, or is empty, Django tries the URL in the
|
||||
``Referrer`` header.
|
||||
* If that's empty -- say, if a user's browser suppresses that header --
|
||||
then the user will be redirected to ``/`` (the site root) as a fallback.
|
||||
|
||||
Here's example HTML template code::
|
||||
|
||||
<form action="/i18n/setlang/" method="post">
|
||||
<input name="next" type="hidden" value="/next/page/" />
|
||||
<select name="language">
|
||||
{% for lang in LANGUAGES %}
|
||||
<option value="{{ lang.0 }}">{{ lang.1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
|
||||
Translations and JavaScript
|
||||
===========================
|
||||
|
||||
@ -752,7 +752,7 @@ The main solution to these problems is the ``javascript_catalog`` view, which
|
||||
sends out a JavaScript code library with functions that mimic the ``gettext``
|
||||
interface, plus an array of translation strings. Those translation strings are
|
||||
taken from the application, project or Django core, according to what you
|
||||
specify in either the {{{info_dict}}} or the URL.
|
||||
specify in either the info_dict or the URL.
|
||||
|
||||
You hook it up like this::
|
||||
|
||||
@ -817,8 +817,8 @@ pluralizations).
|
||||
Creating JavaScript translation catalogs
|
||||
----------------------------------------
|
||||
|
||||
You create and update the translation catalogs the same way as the other Django
|
||||
translation catalogs -- with the {{{make-messages.py}}} tool. The only
|
||||
You create and update the translation catalogs the same way as the other
|
||||
Django translation catalogs -- with the make-messages.py tool. The only
|
||||
difference is you need to provide a ``-d djangojs`` parameter, like this::
|
||||
|
||||
make-messages.py -d djangojs -l de
|
||||
@ -827,13 +827,13 @@ This would create or update the translation catalog for JavaScript for German.
|
||||
After updating translation catalogs, just run ``compile-messages.py`` the same
|
||||
way as you do with normal Django translation catalogs.
|
||||
|
||||
Specialities of Django translation
|
||||
Specialties of Django translation
|
||||
==================================
|
||||
|
||||
If you know ``gettext``, you might note these specialities in the way Django
|
||||
If you know ``gettext``, you might note these specialties in the way Django
|
||||
does translation:
|
||||
|
||||
* The string domain is ``django`` or ``djangojs``. The string domain is
|
||||
* The string domain is ``django`` or ``djangojs``. This string domain is
|
||||
used to differentiate between different programs that store their data
|
||||
in a common message-file library (usually ``/usr/share/locale/``). The
|
||||
``django`` domain is used for python and template translation strings
|
||||
@ -841,5 +841,5 @@ does translation:
|
||||
domain is only used for JavaScript translation catalogs to make sure
|
||||
that those are as small as possible.
|
||||
* Django doesn't use ``xgettext`` alone. It uses Python wrappers around
|
||||
``xgettext`` and ``msgfmt``. That's mostly for convenience.
|
||||
``xgettext`` and ``msgfmt``. This is mostly for convenience.
|
||||
|
||||
|
@ -67,6 +67,16 @@ installed.
|
||||
|
||||
* If you're using Oracle, you'll need cx_Oracle_, version 4.3.1 or higher.
|
||||
|
||||
If you plan to use Django's ``manage.py syncdb`` command to
|
||||
automatically create database tables for your models, you'll need to
|
||||
ensure that Django has permission to create tables in the database
|
||||
you're using; if you plan to manually create the tables, you can
|
||||
simply grant Django ``SELECT``, ``INSERT``, ``UPDATE`` and ``DELETE``
|
||||
permissions. Django does not issue ``ALTER TABLE`` statements, and so
|
||||
will not require permission to do so. If you will be using Django's
|
||||
`testing framework`_ with data fixtures, Django will need permission
|
||||
to create a temporary test database.
|
||||
|
||||
.. _PostgreSQL: http://www.postgresql.org/
|
||||
.. _MySQL: http://www.mysql.com/
|
||||
.. _Django's ticket system: http://code.djangoproject.com/report/1
|
||||
@ -78,6 +88,7 @@ installed.
|
||||
.. _MySQL backend: ../databases/
|
||||
.. _cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/
|
||||
.. _Oracle: http://www.oracle.com/
|
||||
.. _testing framework: ../testing/
|
||||
|
||||
Remove any old versions of Django
|
||||
=================================
|
||||
|
@ -776,6 +776,27 @@ form data *and* file data::
|
||||
# Unbound form with a image field
|
||||
>>> f = ContactFormWithMugshot()
|
||||
|
||||
Testing for multipart forms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you're writing reusable views or templates, you may not know ahead of time
|
||||
whether your form is a multipart form or not. The ``is_multipart()`` method
|
||||
tells you whether the form requires multipart encoding for submission::
|
||||
|
||||
>>> f = ContactFormWithMugshot()
|
||||
>>> f.is_multipart()
|
||||
True
|
||||
|
||||
Here's an example of how you might use this in a template::
|
||||
|
||||
{% if form.is_multipart %}
|
||||
<form enctype="multipart/form-data" method="post" action="/foo/">
|
||||
{% else %}
|
||||
<form method="post" action="/foo/">
|
||||
{% endif %}
|
||||
{% form %}
|
||||
</form>
|
||||
|
||||
Subclassing forms
|
||||
-----------------
|
||||
|
||||
|
@ -1419,6 +1419,12 @@ A collection of template filters that implement these common markup languages:
|
||||
* Markdown
|
||||
* ReST (ReStructured Text)
|
||||
|
||||
See the `markup section`_ of the `add-ons documentation`_ for more
|
||||
information.
|
||||
|
||||
.. _markup section: ../add_ons/#markup
|
||||
.. _add-ons documentation: ../add_ons/
|
||||
|
||||
django.contrib.webdesign
|
||||
------------------------
|
||||
|
||||
|
@ -137,12 +137,14 @@ When you `run your tests`_, the test runner will find this docstring, notice
|
||||
that portions of it look like an interactive Python session, and execute those
|
||||
lines while checking that the results match.
|
||||
|
||||
In the case of model tests, note that the test runner takes care of creating
|
||||
its own test database. That is, any test that accesses a database -- by
|
||||
creating and saving model instances, for example -- will not affect your
|
||||
production database. Each doctest begins with a "blank slate" -- a fresh
|
||||
database containing an empty table for each model. (See the section on
|
||||
fixtures, below, for more on this.)
|
||||
In the case of model tests, note that the test runner takes care of
|
||||
creating its own test database. That is, any test that accesses a
|
||||
database -- by creating and saving model instances, for example --
|
||||
will not affect your production database. Each doctest begins with a
|
||||
"blank slate" -- a fresh database containing an empty table for each
|
||||
model. (See the section on fixtures, below, for more on this.) Note
|
||||
that to use this feature, the database user Django is connecting as
|
||||
must have ``CREATE DATABASE`` rights.
|
||||
|
||||
For more details about how doctest works, see the `standard library
|
||||
documentation for doctest`_
|
||||
|
@ -46,7 +46,7 @@ will create a ``mysite`` directory in your current directory.
|
||||
If you're using Mac OS X, you may see the message "permission
|
||||
denied" when you try to run ``django-admin.py startproject``. This
|
||||
is because, on Unix-based systems like OS X, a file must be marked
|
||||
as "exceutable" before it can be run as a program. To do this, open
|
||||
as "executable" before it can be run as a program. To do this, open
|
||||
Terminal.app and navigate (using the `cd` command) to the directory
|
||||
where ``django-admin.py`` is installed, then run the command
|
||||
``chmod +x django-admin.py``.
|
||||
|
@ -74,7 +74,7 @@ Multiple fixtures named 'fixture2' in '...fixtures'. Aborting.
|
||||
|
||||
# Dump the current contents of the database as a JSON fixture
|
||||
>>> management.call_command('dumpdata', 'fixtures', format='json')
|
||||
[{"pk": "3", "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "2", "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": "1", "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]
|
||||
[{"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]
|
||||
"""}
|
||||
|
||||
from django.test import TestCase
|
||||
|
@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
41. Serialization
|
||||
|
||||
@ -43,6 +44,25 @@ class AuthorProfile(models.Model):
|
||||
|
||||
def __unicode__(self):
|
||||
return u"Profile of %s" % self.author
|
||||
|
||||
class Actor(models.Model):
|
||||
name = models.CharField(max_length=20, primary_key=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ('name',)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class Movie(models.Model):
|
||||
actor = models.ForeignKey(Actor)
|
||||
title = models.CharField(max_length=50)
|
||||
|
||||
class Meta:
|
||||
ordering = ('title',)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
__test__ = {'API_TESTS':"""
|
||||
# Create some data:
|
||||
@ -101,7 +121,7 @@ __test__ = {'API_TESTS':"""
|
||||
# Django also ships with a built-in JSON serializers
|
||||
>>> json = serializers.serialize("json", Category.objects.filter(pk=2))
|
||||
>>> json
|
||||
'[{"pk": "2", "model": "serializers.category", "fields": {"name": "Music"}}]'
|
||||
'[{"pk": 2, "model": "serializers.category", "fields": {"name": "Music"}}]'
|
||||
|
||||
# You can easily create new objects by deserializing data with an empty PK
|
||||
# (It's easier to demo this with JSON...)
|
||||
@ -133,7 +153,7 @@ __test__ = {'API_TESTS':"""
|
||||
|
||||
>>> json = serializers.serialize("json", AuthorProfile.objects.all())
|
||||
>>> json
|
||||
'[{"pk": "1", "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]'
|
||||
'[{"pk": 1, "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]'
|
||||
|
||||
>>> for obj in serializers.deserialize("json", json):
|
||||
... print obj
|
||||
@ -141,7 +161,7 @@ __test__ = {'API_TESTS':"""
|
||||
|
||||
# Objects ids can be referenced before they are defined in the serialization data
|
||||
# However, the deserialization process will need to be contained within a transaction
|
||||
>>> json = '[{"pk": "3", "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00", "categories": [4, 1], "author": 4}}, {"pk": "4", "model": "serializers.category", "fields": {"name": "Reference"}}, {"pk": "4", "model": "serializers.author", "fields": {"name": "Agnes"}}]'
|
||||
>>> json = '[{"pk": 3, "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00", "categories": [4, 1], "author": 4}}, {"pk": 4, "model": "serializers.category", "fields": {"name": "Reference"}}, {"pk": 4, "model": "serializers.author", "fields": {"name": "Agnes"}}]'
|
||||
>>> from django.db import transaction
|
||||
>>> transaction.enter_transaction_management()
|
||||
>>> transaction.managed(True)
|
||||
@ -161,6 +181,30 @@ __test__ = {'API_TESTS':"""
|
||||
|
||||
# Serializer output can be restricted to a subset of fields
|
||||
>>> print serializers.serialize("json", Article.objects.all(), fields=('headline','pub_date'))
|
||||
[{"pk": "1", "model": "serializers.article", "fields": {"headline": "Just kidding; I love TV poker", "pub_date": "2006-06-16 11:00:00"}}, {"pk": "2", "model": "serializers.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "3", "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00"}}]
|
||||
[{"pk": 1, "model": "serializers.article", "fields": {"headline": "Just kidding; I love TV poker", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 2, "model": "serializers.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 3, "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00"}}]
|
||||
|
||||
# Every string is serialized as a unicode object, also primary key
|
||||
# which is 'varchar'
|
||||
>>> ac = Actor(name="Zażółć")
|
||||
>>> mv = Movie(title="Gęślą jaźń", actor=ac)
|
||||
>>> ac.save(); mv.save()
|
||||
|
||||
# Let's serialize our movie
|
||||
>>> print serializers.serialize("json", [mv])
|
||||
[{"pk": 1, "model": "serializers.movie", "fields": {"actor": "Za\u017c\u00f3\u0142\u0107", "title": "G\u0119\u015bl\u0105 ja\u017a\u0144"}}]
|
||||
|
||||
# Deserialization of movie
|
||||
>>> list(serializers.deserialize('json', serializers.serialize('json', [mv])))[0].object.title
|
||||
u'G\u0119\u015bl\u0105 ja\u017a\u0144'
|
||||
|
||||
# None is null after serialization to json
|
||||
# Primary key is None in case of not saved model
|
||||
>>> mv2 = Movie(title="Movie 2", actor=ac)
|
||||
>>> print serializers.serialize("json", [mv2])
|
||||
[{"pk": null, "model": "serializers.movie", "fields": {"actor": "Za\u017c\u00f3\u0142\u0107", "title": "Movie 2"}}]
|
||||
|
||||
# Deserialization of null returns None for pk
|
||||
>>> print list(serializers.deserialize('json', serializers.serialize('json', [mv2])))[0].object.id
|
||||
None
|
||||
|
||||
"""}
|
||||
|
0
tests/modeltests/signals/__init__.py
Normal file
0
tests/modeltests/signals/__init__.py
Normal file
85
tests/modeltests/signals/models.py
Normal file
85
tests/modeltests/signals/models.py
Normal file
@ -0,0 +1,85 @@
|
||||
"""
|
||||
Testing signals before/after saving and deleting.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
from django.dispatch import dispatcher
|
||||
|
||||
class Person(models.Model):
|
||||
first_name = models.CharField(max_length=20)
|
||||
last_name = models.CharField(max_length=20)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s %s" % (self.first_name, self.last_name)
|
||||
|
||||
|
||||
def pre_save_test(sender, instance, **kwargs):
|
||||
print 'pre_save signal,', instance
|
||||
|
||||
def post_save_test(sender, instance, **kwargs):
|
||||
print 'post_save signal,', instance
|
||||
if 'created' in kwargs:
|
||||
if kwargs['created']:
|
||||
print 'Is created'
|
||||
else:
|
||||
print 'Is updated'
|
||||
|
||||
def pre_delete_test(sender, instance, **kwargs):
|
||||
print 'pre_delete signal,', instance
|
||||
print 'instance.id is not None: %s' % (instance.id != None)
|
||||
|
||||
def post_delete_test(sender, instance, **kwargs):
|
||||
print 'post_delete signal,', instance
|
||||
print 'instance.id is None: %s' % (instance.id == None)
|
||||
|
||||
__test__ = {'API_TESTS':"""
|
||||
>>> dispatcher.connect(pre_save_test, signal=models.signals.pre_save)
|
||||
>>> dispatcher.connect(post_save_test, signal=models.signals.post_save)
|
||||
>>> dispatcher.connect(pre_delete_test, signal=models.signals.pre_delete)
|
||||
>>> dispatcher.connect(post_delete_test, signal=models.signals.post_delete)
|
||||
|
||||
>>> p1 = Person(first_name='John', last_name='Smith')
|
||||
>>> p1.save()
|
||||
pre_save signal, John Smith
|
||||
post_save signal, John Smith
|
||||
Is created
|
||||
|
||||
>>> p1.first_name = 'Tom'
|
||||
>>> p1.save()
|
||||
pre_save signal, Tom Smith
|
||||
post_save signal, Tom Smith
|
||||
Is updated
|
||||
|
||||
>>> p1.delete()
|
||||
pre_delete signal, Tom Smith
|
||||
instance.id is not None: True
|
||||
post_delete signal, Tom Smith
|
||||
instance.id is None: True
|
||||
|
||||
>>> p2 = Person(first_name='James', last_name='Jones')
|
||||
>>> p2.id = 99999
|
||||
>>> p2.save()
|
||||
pre_save signal, James Jones
|
||||
post_save signal, James Jones
|
||||
Is created
|
||||
|
||||
>>> p2.id = 99998
|
||||
>>> p2.save()
|
||||
pre_save signal, James Jones
|
||||
post_save signal, James Jones
|
||||
Is created
|
||||
|
||||
>>> p2.delete()
|
||||
pre_delete signal, James Jones
|
||||
instance.id is not None: True
|
||||
post_delete signal, James Jones
|
||||
instance.id is None: True
|
||||
|
||||
>>> Person.objects.all()
|
||||
[<Person: James Jones>]
|
||||
|
||||
>>> dispatcher.disconnect(post_delete_test, signal=models.signals.post_delete)
|
||||
>>> dispatcher.disconnect(pre_delete_test, signal=models.signals.pre_delete)
|
||||
>>> dispatcher.disconnect(post_save_test, signal=models.signals.post_save)
|
||||
>>> dispatcher.disconnect(pre_save_test, signal=models.signals.pre_save)
|
||||
"""}
|
@ -0,0 +1,21 @@
|
||||
from django.db import models
|
||||
|
||||
class BoundaryModel(models.Model):
|
||||
positive_integer = models.PositiveIntegerField(null=True, blank=True)
|
||||
|
||||
__test__ = {'API_TESTS': """
|
||||
>>> from django.newforms import form_for_model
|
||||
|
||||
# Boundary conditions on a PostitiveIntegerField #########################
|
||||
>>> BoundaryForm = form_for_model(BoundaryModel)
|
||||
>>> f = BoundaryForm({'positive_integer':100})
|
||||
>>> f.is_valid()
|
||||
True
|
||||
>>> f = BoundaryForm({'positive_integer':0})
|
||||
>>> f.is_valid()
|
||||
True
|
||||
>>> f = BoundaryForm({'positive_integer':-100})
|
||||
>>> f.is_valid()
|
||||
False
|
||||
|
||||
"""}
|
@ -60,6 +60,12 @@ Translated error messages used to be buggy.
|
||||
u'<ul class="errorlist"><li>\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435.</li></ul>\n<p><label for="id_somechoice_0">\xc5\xf8\xdf:</label> <ul>\n<li><label><input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" /> En tied\xe4</label></li>\n<li><label><input type="radio" id="id_somechoice_1" value="\xf8" name="somechoice" /> Mies</label></li>\n<li><label><input type="radio" id="id_somechoice_2" value="\xdf" name="somechoice" /> Nainen</label></li>\n</ul></p>'
|
||||
>>> deactivate()
|
||||
|
||||
Deep copying translated text shouldn't raise an error
|
||||
>>> from django.utils.translation import gettext_lazy
|
||||
>>> class CopyForm(Form):
|
||||
... degree = IntegerField(widget=Select(choices=((1, gettext_lazy('test')),)))
|
||||
>>> f = CopyForm()
|
||||
|
||||
#######################
|
||||
# Miscellaneous Tests #
|
||||
#######################
|
||||
|
@ -961,6 +961,12 @@ True
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a whole number.']
|
||||
>>> f.clean(42)
|
||||
42
|
||||
>>> f.clean(3.14)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a whole number.']
|
||||
>>> f.clean('1 ')
|
||||
1
|
||||
>>> f.clean(' 1')
|
||||
@ -1084,6 +1090,10 @@ True
|
||||
23.0
|
||||
>>> f.clean('3.14')
|
||||
3.1400000000000001
|
||||
>>> f.clean(3.14)
|
||||
3.1400000000000001
|
||||
>>> f.clean(42)
|
||||
42.0
|
||||
>>> f.clean('a')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
@ -1142,6 +1152,10 @@ True
|
||||
Decimal("23")
|
||||
>>> f.clean('3.14')
|
||||
Decimal("3.14")
|
||||
>>> f.clean(3.14)
|
||||
Decimal("3.14")
|
||||
>>> f.clean(Decimal('3.14'))
|
||||
Decimal("3.14")
|
||||
>>> f.clean('a')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
@ -3856,6 +3870,25 @@ u'sirrobin'
|
||||
<div class="errorlist"><div class="error">This field is required.</div></div>
|
||||
<p>Comment: <input type="text" name="comment" /></p>
|
||||
|
||||
#################################
|
||||
# Test multipart-encoded form #
|
||||
#################################
|
||||
|
||||
>>> class FormWithoutFile(Form):
|
||||
... username = CharField()
|
||||
>>> class FormWithFile(Form):
|
||||
... username = CharField()
|
||||
... file = FileField()
|
||||
>>> class FormWithImage(Form):
|
||||
... image = ImageField()
|
||||
|
||||
>>> FormWithoutFile().is_multipart()
|
||||
False
|
||||
>>> FormWithFile().is_multipart()
|
||||
True
|
||||
>>> FormWithImage().is_multipart()
|
||||
True
|
||||
|
||||
"""
|
||||
|
||||
__test__ = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user