1
0
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:
Adrian Holovaty 2007-09-15 21:57:25 +00:00
parent 7325fbf4ff
commit ca33d307de
71 changed files with 11937 additions and 5965 deletions

View File

@ -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>

View File

@ -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)

View File

@ -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')),

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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.

View 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 ""

View File

@ -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");})()');

View File

@ -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)

View File

@ -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):

View File

@ -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()
[]
"""

View File

@ -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()

View File

@ -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

View 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

View 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'),
)

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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 = ''

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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::

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -920,10 +920,20 @@ 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)

View File

@ -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()

View File

@ -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

View File

@ -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,

View File

@ -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()

View File

@ -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):

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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):
"""

View File

@ -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 '.')
"""

View File

@ -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)

View File

@ -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():

View File

@ -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"

View File

@ -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__'):

View File

@ -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",

View File

@ -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)

View File

@ -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 = []

View File

@ -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):

View File

@ -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::

View File

@ -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
===================

View File

@ -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``,

View File

@ -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::

View File

@ -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/

View File

@ -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
~~~~~~~~~~~~~~~~~~~

View File

@ -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.

View File

@ -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
=================================

View File

@ -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
-----------------

View File

@ -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
------------------------

View File

@ -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`_

View File

@ -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``.

View File

@ -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

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
41. Serialization
@ -44,6 +45,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:
>>> from datetime import datetime
@ -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
"""}

View File

View 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)
"""}

View File

@ -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
"""}

View File

@ -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 #
#######################

View File

@ -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__ = {