1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

schema-evolution: update from HEAD (v5821)

git-svn-id: http://code.djangoproject.com/svn/django/branches/schema-evolution@5822 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Derek Anderson 2007-08-06 16:50:17 +00:00
parent 0af6ed0c48
commit 5aa0172558
111 changed files with 1068 additions and 487 deletions

View File

@ -45,6 +45,7 @@ answer newbie questions, and generally made Django that much better:
Marty Alchin <gulopine@gamemusic.org> Marty Alchin <gulopine@gamemusic.org>
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com> Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
AgarFu <heaven@croasanaso.sytes.net> AgarFu <heaven@croasanaso.sytes.net>
Derek Anderson <public@kered.org>
Andreas Andreas
andy@jadedplanet.net andy@jadedplanet.net
Fabrice Aneche <akh@nobugware.com> Fabrice Aneche <akh@nobugware.com>
@ -96,6 +97,7 @@ answer newbie questions, and generally made Django that much better:
Maximillian Dornseif <md@hudora.de> Maximillian Dornseif <md@hudora.de>
Jeremy Dunck <http://dunck.us/> Jeremy Dunck <http://dunck.us/>
Andrew Durdin <adurdin@gmail.com> Andrew Durdin <adurdin@gmail.com>
dusk@woofle.net
Andy Dustman <farcepest@gmail.com> Andy Dustman <farcepest@gmail.com>
Clint Ecker Clint Ecker
enlight enlight

View File

@ -18,7 +18,7 @@ class LogEntry(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType, blank=True, null=True) content_type = models.ForeignKey(ContentType, blank=True, null=True)
object_id = models.TextField(_('object id'), blank=True, null=True) object_id = models.TextField(_('object id'), blank=True, null=True)
object_repr = models.CharField(_('object repr'), maxlength=200) object_repr = models.CharField(_('object repr'), max_length=200)
action_flag = models.PositiveSmallIntegerField(_('action flag')) action_flag = models.PositiveSmallIntegerField(_('action flag'))
change_message = models.TextField(_('change message'), blank=True) change_message = models.TextField(_('change message'), blank=True)
objects = LogEntryManager() objects = LogEntryManager()

View File

@ -192,7 +192,7 @@ def auto_populated_field_script(auto_pop_fields, change = False):
t.append(u'document.getElementById("id_%s").onkeyup = function() {' \ t.append(u'document.getElementById("id_%s").onkeyup = function() {' \
' var e = document.getElementById("id_%s");' \ ' var e = document.getElementById("id_%s");' \
' if(!e._changed) { e.value = URLify(%s, %s);} }; ' % ( ' if(!e._changed) { e.value = URLify(%s, %s);} }; ' % (
f, field.name, add_values, field.maxlength)) f, field.name, add_values, field.max_length))
return u''.join(t) return u''.join(t)
auto_populated_field_script = register.simple_tag(auto_populated_field_script) auto_populated_field_script = register.simple_tag(auto_populated_field_script)

View File

@ -291,7 +291,7 @@ def get_return_data_type(func_name):
DATA_TYPE_MAPPING = { DATA_TYPE_MAPPING = {
'AutoField' : _('Integer'), 'AutoField' : _('Integer'),
'BooleanField' : _('Boolean (Either True or False)'), 'BooleanField' : _('Boolean (Either True or False)'),
'CharField' : _('String (up to %(maxlength)s)'), 'CharField' : _('String (up to %(max_length)s)'),
'CommaSeparatedIntegerField': _('Comma-separated integers'), 'CommaSeparatedIntegerField': _('Comma-separated integers'),
'DateField' : _('Date (without time)'), 'DateField' : _('Date (without time)'),
'DateTimeField' : _('Date (with time)'), 'DateTimeField' : _('Date (with time)'),
@ -310,7 +310,7 @@ DATA_TYPE_MAPPING = {
'PhoneNumberField' : _('Phone number'), 'PhoneNumberField' : _('Phone number'),
'PositiveIntegerField' : _('Integer'), 'PositiveIntegerField' : _('Integer'),
'PositiveSmallIntegerField' : _('Integer'), 'PositiveSmallIntegerField' : _('Integer'),
'SlugField' : _('String (up to %(maxlength)s)'), 'SlugField' : _('String (up to %(max_length)s)'),
'SmallIntegerField' : _('Integer'), 'SmallIntegerField' : _('Integer'),
'TextField' : _('Text'), 'TextField' : _('Text'),
'TimeField' : _('Time'), 'TimeField' : _('Time'),

View File

@ -673,7 +673,7 @@ class ChangeList(object):
try: try:
attr = getattr(lookup_opts.admin.manager.model, field_name) attr = getattr(lookup_opts.admin.manager.model, field_name)
order_field = attr.admin_order_field order_field = attr.admin_order_field
except IndexError: except AttributeError:
pass pass
else: else:
if not isinstance(f.rel, models.ManyToOneRel) or not f.null: if not isinstance(f.rel, models.ManyToOneRel) or not f.null:

View File

@ -10,10 +10,10 @@ class UserCreationForm(oldforms.Manipulator):
"A form that creates a user, with no privileges, from the given username and password." "A form that creates a user, with no privileges, from the given username and password."
def __init__(self): def __init__(self):
self.fields = ( self.fields = (
oldforms.TextField(field_name='username', length=30, maxlength=30, is_required=True, oldforms.TextField(field_name='username', length=30, max_length=30, is_required=True,
validator_list=[validators.isAlphaNumeric, self.isValidUsername]), validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
oldforms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True), oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True, oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]), validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
) )
@ -42,9 +42,9 @@ class AuthenticationForm(oldforms.Manipulator):
""" """
self.request = request self.request = request
self.fields = [ self.fields = [
oldforms.TextField(field_name="username", length=15, maxlength=30, is_required=True, oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
validator_list=[self.isValidUser, self.hasCookiesEnabled]), validator_list=[self.isValidUser, self.hasCookiesEnabled]),
oldforms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True), oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
] ]
self.user_cache = None self.user_cache = None
@ -111,11 +111,11 @@ class PasswordChangeForm(oldforms.Manipulator):
def __init__(self, user): def __init__(self, user):
self.user = user self.user = user
self.fields = ( self.fields = (
oldforms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True, oldforms.PasswordField(field_name="old_password", length=30, max_length=30, is_required=True,
validator_list=[self.isValidOldPassword]), validator_list=[self.isValidOldPassword]),
oldforms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True, oldforms.PasswordField(field_name="new_password1", length=30, max_length=30, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]), validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
oldforms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True), oldforms.PasswordField(field_name="new_password2", length=30, max_length=30, is_required=True),
) )
def isValidOldPassword(self, new_data, all_data): def isValidOldPassword(self, new_data, all_data):
@ -133,8 +133,8 @@ class AdminPasswordChangeForm(oldforms.Manipulator):
def __init__(self, user): def __init__(self, user):
self.user = user self.user = user
self.fields = ( self.fields = (
oldforms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True), oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True, oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]), validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
) )

View File

@ -50,9 +50,9 @@ class Permission(models.Model):
Three basic permissions -- add, change and delete -- are automatically created for each Django model. Three basic permissions -- add, change and delete -- are automatically created for each Django model.
""" """
name = models.CharField(_('name'), maxlength=50) name = models.CharField(_('name'), max_length=50)
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType)
codename = models.CharField(_('codename'), maxlength=100) codename = models.CharField(_('codename'), max_length=100)
class Meta: class Meta:
verbose_name = _('permission') verbose_name = _('permission')
@ -70,7 +70,7 @@ class Group(models.Model):
Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages. Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages.
""" """
name = models.CharField(_('name'), maxlength=80, unique=True) name = models.CharField(_('name'), max_length=80, unique=True)
permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True, filter_interface=models.HORIZONTAL) permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True, filter_interface=models.HORIZONTAL)
class Meta: class Meta:
@ -108,11 +108,11 @@ class User(models.Model):
Username and password are required. Other fields are optional. Username and password are required. Other fields are optional.
""" """
username = models.CharField(_('username'), maxlength=30, unique=True, validator_list=[validators.isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).")) username = models.CharField(_('username'), max_length=30, unique=True, validator_list=[validators.isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
first_name = models.CharField(_('first name'), maxlength=30, blank=True) first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), maxlength=30, blank=True) last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('e-mail address'), blank=True) email = models.EmailField(_('e-mail address'), blank=True)
password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>.")) password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site.")) is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts.")) is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts."))
is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them.")) is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))

View File

@ -65,8 +65,8 @@ class Comment(models.Model):
user = models.ForeignKey(User, raw_id_admin=True) user = models.ForeignKey(User, raw_id_admin=True)
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID')) object_id = models.IntegerField(_('object ID'))
headline = models.CharField(_('headline'), maxlength=255, blank=True) headline = models.CharField(_('headline'), max_length=255, blank=True)
comment = models.TextField(_('comment'), maxlength=3000) comment = models.TextField(_('comment'), max_length=3000)
rating1 = models.PositiveSmallIntegerField(_('rating #1'), blank=True, null=True) rating1 = models.PositiveSmallIntegerField(_('rating #1'), blank=True, null=True)
rating2 = models.PositiveSmallIntegerField(_('rating #2'), blank=True, null=True) rating2 = models.PositiveSmallIntegerField(_('rating #2'), blank=True, null=True)
rating3 = models.PositiveSmallIntegerField(_('rating #3'), blank=True, null=True) rating3 = models.PositiveSmallIntegerField(_('rating #3'), blank=True, null=True)
@ -164,8 +164,8 @@ class FreeComment(models.Model):
# A FreeComment is a comment by a non-registered user. # A FreeComment is a comment by a non-registered user.
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID')) object_id = models.IntegerField(_('object ID'))
comment = models.TextField(_('comment'), maxlength=3000) comment = models.TextField(_('comment'), max_length=3000)
person_name = models.CharField(_("person's name"), maxlength=50) person_name = models.CharField(_("person's name"), max_length=50)
submit_date = models.DateTimeField(_('date/time submitted'), auto_now_add=True) submit_date = models.DateTimeField(_('date/time submitted'), auto_now_add=True)
is_public = models.BooleanField(_('is public')) is_public = models.BooleanField(_('is public'))
ip_address = models.IPAddressField(_('ip address')) ip_address = models.IPAddressField(_('ip address'))

View File

@ -29,7 +29,7 @@ class PublicCommentManipulator(AuthenticationForm):
else: else:
return [] return []
self.fields.extend([ self.fields.extend([
oldforms.LargeTextField(field_name="comment", maxlength=3000, is_required=True, oldforms.LargeTextField(field_name="comment", max_length=3000, is_required=True,
validator_list=[self.hasNoProfanities]), validator_list=[self.hasNoProfanities]),
oldforms.RadioSelectField(field_name="rating1", choices=choices, oldforms.RadioSelectField(field_name="rating1", choices=choices,
is_required=ratings_required and num_rating_choices > 0, is_required=ratings_required and num_rating_choices > 0,
@ -122,9 +122,9 @@ class PublicFreeCommentManipulator(oldforms.Manipulator):
"Manipulator that handles public free (unregistered) comments" "Manipulator that handles public free (unregistered) comments"
def __init__(self): def __init__(self):
self.fields = ( self.fields = (
oldforms.TextField(field_name="person_name", maxlength=50, is_required=True, oldforms.TextField(field_name="person_name", max_length=50, is_required=True,
validator_list=[self.hasNoProfanities]), validator_list=[self.hasNoProfanities]),
oldforms.LargeTextField(field_name="comment", maxlength=3000, is_required=True, oldforms.LargeTextField(field_name="comment", max_length=3000, is_required=True,
validator_list=[self.hasNoProfanities]), validator_list=[self.hasNoProfanities]),
) )

View File

@ -32,9 +32,9 @@ class ContentTypeManager(models.Manager):
CONTENT_TYPE_CACHE = {} CONTENT_TYPE_CACHE = {}
class ContentType(models.Model): class ContentType(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
app_label = models.CharField(maxlength=100) app_label = models.CharField(max_length=100)
model = models.CharField(_('python model class name'), maxlength=100) model = models.CharField(_('python model class name'), max_length=100)
objects = ContentTypeManager() objects = ContentTypeManager()
class Meta: class Meta:
verbose_name = _('content type') verbose_name = _('content type')

View File

@ -4,12 +4,12 @@ from django.contrib.sites.models import Site
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
class FlatPage(models.Model): class FlatPage(models.Model):
url = models.CharField(_('URL'), maxlength=100, validator_list=[validators.isAlphaNumericURL], db_index=True, url = models.CharField(_('URL'), max_length=100, validator_list=[validators.isAlphaNumericURL], db_index=True,
help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes.")) help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes."))
title = models.CharField(_('title'), maxlength=200) title = models.CharField(_('title'), max_length=200)
content = models.TextField(_('content')) content = models.TextField(_('content'))
enable_comments = models.BooleanField(_('enable comments')) enable_comments = models.BooleanField(_('enable comments'))
template_name = models.CharField(_('template name'), maxlength=70, blank=True, template_name = models.CharField(_('template name'), max_length=70, blank=True,
help_text=_("Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'.")) help_text=_("Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'."))
registration_required = models.BooleanField(_('registration required'), help_text=_("If this is checked, only logged-in users will be able to view the page.")) registration_required = models.BooleanField(_('registration required'), help_text=_("If this is checked, only logged-in users will be able to view the page."))
sites = models.ManyToManyField(Site) sites = models.ManyToManyField(Site)

View File

@ -4,9 +4,9 @@ from django.utils.translation import ugettext_lazy as _
class Redirect(models.Model): class Redirect(models.Model):
site = models.ForeignKey(Site, radio_admin=models.VERTICAL) site = models.ForeignKey(Site, radio_admin=models.VERTICAL)
old_path = models.CharField(_('redirect from'), maxlength=200, db_index=True, old_path = models.CharField(_('redirect from'), max_length=200, db_index=True,
help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'.")) help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'."))
new_path = models.CharField(_('redirect to'), maxlength=200, blank=True, new_path = models.CharField(_('redirect to'), max_length=200, blank=True,
help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'.")) help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'."))
class Meta: class Meta:

View File

@ -65,7 +65,7 @@ class Session(models.Model):
the sessions documentation that is shipped with Django (also available the sessions documentation that is shipped with Django (also available
on the Django website). on the Django website).
""" """
session_key = models.CharField(_('session key'), maxlength=40, primary_key=True) session_key = models.CharField(_('session key'), max_length=40, primary_key=True)
session_data = models.TextField(_('session data')) session_data = models.TextField(_('session data'))
expire_date = models.DateTimeField(_('expire date')) expire_date = models.DateTimeField(_('expire date'))
objects = SessionManager() objects = SessionManager()

View File

@ -12,8 +12,8 @@ class SiteManager(models.Manager):
return self.get(pk=sid) return self.get(pk=sid)
class Site(models.Model): class Site(models.Model):
domain = models.CharField(_('domain name'), maxlength=100) domain = models.CharField(_('domain name'), max_length=100)
name = models.CharField(_('display name'), maxlength=50) name = models.CharField(_('display name'), max_length=50)
objects = SiteManager() objects = SiteManager()
class Meta: class Meta:
db_table = 'django_site' db_table = 'django_site'

View File

@ -1064,9 +1064,9 @@ def inspectdb():
field_type, new_params = field_type field_type, new_params = field_type
extra_params.update(new_params) extra_params.update(new_params)
# Add maxlength for all CharFields. # Add max_length for all CharFields.
if field_type == 'CharField' and row[3]: if field_type == 'CharField' and row[3]:
extra_params['maxlength'] = row[3] extra_params['max_length'] = row[3]
if field_type == 'DecimalField': if field_type == 'DecimalField':
extra_params['max_digits'] = row[4] extra_params['max_digits'] = row[4]
@ -1141,8 +1141,8 @@ def get_validation_errors(outfile, app=None):
for f in opts.fields: for f in opts.fields:
if f.name == 'id' and not f.primary_key and opts.pk.name == 'id': if f.name == 'id' and not f.primary_key and opts.pk.name == 'id':
e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name) e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name)
if isinstance(f, models.CharField) and f.maxlength in (None, 0): if isinstance(f, models.CharField) and f.max_length in (None, 0):
e.add(opts, '"%s": CharFields require a "maxlength" attribute.' % f.name) e.add(opts, '"%s": CharFields require a "max_length" attribute.' % f.name)
if isinstance(f, models.DecimalField): if isinstance(f, models.DecimalField):
if f.decimal_places is None: if f.decimal_places is None:
e.add(opts, '"%s": DecimalFields require a "decimal_places" attribute.' % f.name) e.add(opts, '"%s": DecimalFields require a "decimal_places" attribute.' % f.name)
@ -1167,11 +1167,11 @@ def get_validation_errors(outfile, app=None):
if f.db_index not in (None, True, False): if f.db_index not in (None, True, False):
e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name) e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)
# Check that maxlength <= 255 if using older MySQL versions. # Check that max_length <= 255 if using older MySQL versions.
if settings.DATABASE_ENGINE == 'mysql': if settings.DATABASE_ENGINE == 'mysql':
db_version = connection.get_server_version() db_version = connection.get_server_version()
if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255: if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.max_length > 255:
e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]]))) e.add(opts, '"%s": %s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]])))
# Check to see if the related field will clash with any # Check to see if the related field will clash with any
# existing fields, m2m fields, m2m related objects or related objects # existing fields, m2m fields, m2m related objects or related objects
@ -1406,7 +1406,7 @@ def createcachetable(tablename):
from django.db import backend, connection, transaction, models from django.db import backend, connection, transaction, models
fields = ( fields = (
# "key" is a reserved word in MySQL, so use "cache_key" instead. # "key" is a reserved word in MySQL, so use "cache_key" instead.
models.CharField(name='cache_key', maxlength=255, unique=True, primary_key=True), models.CharField(name='cache_key', max_length=255, unique=True, primary_key=True),
models.TextField(name='value'), models.TextField(name='value'),
models.DateTimeField(name='expires', db_index=True), models.DateTimeField(name='expires', db_index=True),
) )
@ -1454,6 +1454,10 @@ def run_shell(use_plain=False):
shell.mainloop() shell.mainloop()
except ImportError: except ImportError:
import code import code
# Set up a dictionary to serve as the environment for the shell, so
# that tab completion works on objects that are imported at runtime.
# See ticket 5082.
imported_objects = {}
try: # Try activating rlcompleter, because it's handy. try: # Try activating rlcompleter, because it's handy.
import readline import readline
except ImportError: except ImportError:
@ -1462,8 +1466,9 @@ def run_shell(use_plain=False):
# We don't have to wrap the following import in a 'try', because # We don't have to wrap the following import in a 'try', because
# we already know 'readline' was imported successfully. # we already know 'readline' was imported successfully.
import rlcompleter import rlcompleter
readline.set_completer(rlcompleter.Completer(imported_objects).complete)
readline.parse_and_bind("tab:complete") readline.parse_and_bind("tab:complete")
code.interact() code.interact(local=imported_objects)
run_shell.args = '[--plain]' run_shell.args = '[--plain]'
def dbshell(): def dbshell():
@ -1578,7 +1583,7 @@ def load_data(fixture_labels, verbosity=1):
print "Installing %s fixture '%s' from %s." % \ print "Installing %s fixture '%s' from %s." % \
(format, fixture_name, humanize(fixture_dir)) (format, fixture_name, humanize(fixture_dir))
try: try:
objects = serializers.deserialize(format, fixture) objects = serializers.deserialize(format, fixture)
for obj in objects: for obj in objects:
count[0] += 1 count[0] += 1
models.add(obj.object.__class__) models.add(obj.object.__class__)

View File

@ -442,7 +442,7 @@ def isValidFloat(field_data, all_data):
try: try:
float(data) float(data)
except ValueError: except ValueError:
raise ValidationError, ugettext("Please enter a valid floating point number.") raise ValidationError, _("Please enter a valid floating point number.")
class HasAllowableSize(object): class HasAllowableSize(object):
""" """

View File

@ -1,8 +1,8 @@
DATA_TYPES = { DATA_TYPES = {
'AutoField': 'int IDENTITY (1, 1)', 'AutoField': 'int IDENTITY (1, 1)',
'BooleanField': 'bit', 'BooleanField': 'bit',
'CharField': 'varchar(%(maxlength)s)', 'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'smalldatetime', 'DateField': 'smalldatetime',
'DateTimeField': 'smalldatetime', 'DateTimeField': 'smalldatetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
@ -17,7 +17,7 @@ DATA_TYPES = {
'PhoneNumberField': 'varchar(20)', 'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)', 'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)',
'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)', 'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)',
'SlugField': 'varchar(%(maxlength)s)', 'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint', 'SmallIntegerField': 'smallint',
'TextField': 'text', 'TextField': 'text',
'TimeField': 'time', 'TimeField': 'time',

View File

@ -5,8 +5,8 @@
DATA_TYPES = { DATA_TYPES = {
'AutoField': 'integer AUTO_INCREMENT', 'AutoField': 'integer AUTO_INCREMENT',
'BooleanField': 'bool', 'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)', 'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date', 'DateField': 'date',
'DateTimeField': 'datetime', 'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
@ -21,7 +21,7 @@ DATA_TYPES = {
'PhoneNumberField': 'varchar(20)', 'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer UNSIGNED', 'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(maxlength)s)', 'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint', 'SmallIntegerField': 'smallint',
'TextField': 'longtext', 'TextField': 'longtext',
'TimeField': 'time', 'TimeField': 'time',

View File

@ -5,8 +5,8 @@
DATA_TYPES = { DATA_TYPES = {
'AutoField': 'integer AUTO_INCREMENT', 'AutoField': 'integer AUTO_INCREMENT',
'BooleanField': 'bool', 'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)', 'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date', 'DateField': 'date',
'DateTimeField': 'datetime', 'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
@ -21,7 +21,7 @@ DATA_TYPES = {
'PhoneNumberField': 'varchar(20)', 'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer UNSIGNED', 'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(maxlength)s)', 'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint', 'SmallIntegerField': 'smallint',
'TextField': 'longtext', 'TextField': 'longtext',
'TimeField': 'time', 'TimeField': 'time',

View File

@ -8,8 +8,8 @@ from django.core import management
DATA_TYPES = { DATA_TYPES = {
'AutoField': 'NUMBER(11)', 'AutoField': 'NUMBER(11)',
'BooleanField': 'NUMBER(1) CHECK (%(column)s IN (0,1))', 'BooleanField': 'NUMBER(1) CHECK (%(column)s IN (0,1))',
'CharField': 'NVARCHAR2(%(maxlength)s)', 'CharField': 'NVARCHAR2(%(max_length)s)',
'CommaSeparatedIntegerField': 'VARCHAR2(%(maxlength)s)', 'CommaSeparatedIntegerField': 'VARCHAR2(%(max_length)s)',
'DateField': 'DATE', 'DateField': 'DATE',
'DateTimeField': 'TIMESTAMP', 'DateTimeField': 'TIMESTAMP',
'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)', 'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)',

View File

@ -5,8 +5,8 @@
DATA_TYPES = { DATA_TYPES = {
'AutoField': 'serial', 'AutoField': 'serial',
'BooleanField': 'boolean', 'BooleanField': 'boolean',
'CharField': 'varchar(%(maxlength)s)', 'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date', 'DateField': 'date',
'DateTimeField': 'timestamp with time zone', 'DateTimeField': 'timestamp with time zone',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
@ -21,7 +21,7 @@ DATA_TYPES = {
'PhoneNumberField': 'varchar(20)', 'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)', 'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)',
'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)', 'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)',
'SlugField': 'varchar(%(maxlength)s)', 'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint', 'SmallIntegerField': 'smallint',
'TextField': 'text', 'TextField': 'text',
'TimeField': 'time', 'TimeField': 'time',

View File

@ -4,8 +4,8 @@
DATA_TYPES = { DATA_TYPES = {
'AutoField': 'integer', 'AutoField': 'integer',
'BooleanField': 'bool', 'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)', 'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date', 'DateField': 'date',
'DateTimeField': 'datetime', 'DateTimeField': 'datetime',
'DecimalField': 'decimal', 'DecimalField': 'decimal',
@ -20,7 +20,7 @@ DATA_TYPES = {
'PhoneNumberField': 'varchar(20)', 'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer unsigned', 'PositiveIntegerField': 'integer unsigned',
'PositiveSmallIntegerField': 'smallint unsigned', 'PositiveSmallIntegerField': 'smallint unsigned',
'SlugField': 'varchar(%(maxlength)s)', 'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint', 'SmallIntegerField': 'smallint',
'TextField': 'text', 'TextField': 'text',
'TimeField': 'time', 'TimeField': 'time',

View File

@ -137,7 +137,7 @@ class FlexibleFieldLookupDict:
import re import re
m = re.search(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$', key) m = re.search(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$', key)
if m: if m:
return ('CharField', {'maxlength': int(m.group(1))}) return ('CharField', {'max_length': int(m.group(1))})
raise KeyError raise KeyError
DATA_TYPES_REVERSE = FlexibleFieldLookupDict() DATA_TYPES_REVERSE = FlexibleFieldLookupDict()

View File

@ -11,6 +11,7 @@ from django.utils.itercompat import tee
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy, ugettext as _ from django.utils.translation import ugettext_lazy, ugettext as _
from django.utils.encoding import smart_unicode, force_unicode, smart_str from django.utils.encoding import smart_unicode, force_unicode, smart_str
from django.utils.maxlength import LegacyMaxlength
import datetime, os, time import datetime, os, time
try: try:
import decimal import decimal
@ -63,6 +64,9 @@ def manipulator_validator_unique(f, opts, self, field_data, all_data):
# getattr(obj, opts.pk.attname) # getattr(obj, opts.pk.attname)
class Field(object): class Field(object):
# Provide backwards compatibility for the maxlength attribute and
# argument for this class and all subclasses.
__metaclass__ = LegacyMaxlength
# Designates whether empty strings fundamentally are allowed at the # Designates whether empty strings fundamentally are allowed at the
# database level. # database level.
@ -72,7 +76,7 @@ class Field(object):
creation_counter = 0 creation_counter = 0
def __init__(self, verbose_name=None, name=None, primary_key=False, def __init__(self, verbose_name=None, name=None, primary_key=False,
maxlength=None, unique=False, blank=False, null=False, db_index=False, max_length=None, unique=False, blank=False, null=False, db_index=False,
core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True, core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True,
prepopulate_from=None, unique_for_date=None, unique_for_month=None, prepopulate_from=None, unique_for_date=None, unique_for_month=None,
unique_for_year=None, validator_list=None, choices=None, radio_admin=None, unique_for_year=None, validator_list=None, choices=None, radio_admin=None,
@ -80,7 +84,7 @@ class Field(object):
self.name = name self.name = name
self.verbose_name = verbose_name self.verbose_name = verbose_name
self.primary_key = primary_key self.primary_key = primary_key
self.maxlength, self.unique = maxlength, unique self.max_length, self.unique = max_length, unique
self.blank, self.null = blank, null self.blank, self.null = blank, null
# Oracle treats the empty string ('') as null, so coerce the null # Oracle treats the empty string ('') as null, so coerce the null
# option whenever '' is a possible value. # option whenever '' is a possible value.
@ -245,8 +249,8 @@ class Field(object):
def prepare_field_objs_and_params(self, manipulator, name_prefix): def prepare_field_objs_and_params(self, manipulator, name_prefix):
params = {'validator_list': self.validator_list[:]} params = {'validator_list': self.validator_list[:]}
if self.maxlength and not self.choices: # Don't give SelectFields a maxlength parameter. if self.max_length and not self.choices: # Don't give SelectFields a max_length parameter.
params['maxlength'] = self.maxlength params['max_length'] = self.max_length
if self.choices: if self.choices:
if self.radio_admin: if self.radio_admin:
@ -377,6 +381,9 @@ class Field(object):
return self._choices return self._choices
choices = property(_get_choices) choices = property(_get_choices)
def save_form_data(self, instance, data):
setattr(instance, self.name, data)
def formfield(self, form_class=forms.CharField, **kwargs): def formfield(self, form_class=forms.CharField, **kwargs):
"Returns a django.newforms.Field instance for this database Field." "Returns a django.newforms.Field instance for this database Field."
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
@ -462,7 +469,7 @@ class CharField(Field):
return smart_unicode(value) return smart_unicode(value)
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'max_length': self.maxlength} defaults = {'max_length': self.max_length}
defaults.update(kwargs) defaults.update(kwargs)
return super(CharField, self).formfield(**defaults) return super(CharField, self).formfield(**defaults)
@ -671,7 +678,7 @@ class DecimalField(Field):
class EmailField(CharField): class EmailField(CharField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
kwargs['maxlength'] = 75 kwargs['max_length'] = 75
CharField.__init__(self, *args, **kwargs) CharField.__init__(self, *args, **kwargs)
def get_internal_type(self): def get_internal_type(self):
@ -693,6 +700,13 @@ class FileField(Field):
self.upload_to = upload_to self.upload_to = upload_to
Field.__init__(self, verbose_name, name, **kwargs) Field.__init__(self, verbose_name, name, **kwargs)
def get_db_prep_save(self, value):
"Returns field's value prepared for saving into a database."
# Need to convert UploadedFile objects provided via a form to unicode for database insertion
if value is None:
return None
return unicode(value)
def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow) field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)
if not self.blank: if not self.blank:
@ -769,6 +783,19 @@ class FileField(Field):
f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename))) f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))
return os.path.normpath(f) return os.path.normpath(f)
def save_form_data(self, instance, data):
if data:
getattr(instance, "save_%s_file" % self.name)(os.path.join(self.upload_to, data.filename), data.content, save=False)
def formfield(self, **kwargs):
defaults = {'form_class': forms.FileField}
# If a file has been provided previously, then the form doesn't require
# that a new file is provided this time.
if 'initial' in kwargs:
defaults['required'] = False
defaults.update(kwargs)
return super(FileField, self).formfield(**defaults)
class FilePathField(Field): class FilePathField(Field):
def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs):
self.path, self.match, self.recursive = path, match, recursive self.path, self.match, self.recursive = path, match, recursive
@ -817,6 +844,10 @@ class ImageField(FileField):
setattr(new_object, self.height_field, getattr(original_object, self.height_field)) setattr(new_object, self.height_field, getattr(original_object, self.height_field))
new_object.save() new_object.save()
def formfield(self, **kwargs):
defaults = {'form_class': forms.ImageField}
return super(ImageField, self).formfield(**defaults)
class IntegerField(Field): class IntegerField(Field):
empty_strings_allowed = False empty_strings_allowed = False
def get_manipulator_field_objs(self): def get_manipulator_field_objs(self):
@ -830,7 +861,7 @@ class IntegerField(Field):
class IPAddressField(Field): class IPAddressField(Field):
empty_strings_allowed = False empty_strings_allowed = False
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
kwargs['maxlength'] = 15 kwargs['max_length'] = 15
Field.__init__(self, *args, **kwargs) Field.__init__(self, *args, **kwargs)
def get_manipulator_field_objs(self): def get_manipulator_field_objs(self):
@ -878,7 +909,7 @@ class PositiveSmallIntegerField(IntegerField):
class SlugField(Field): class SlugField(Field):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
kwargs['maxlength'] = kwargs.get('maxlength', 50) kwargs['max_length'] = kwargs.get('max_length', 50)
kwargs.setdefault('validator_list', []).append(validators.isSlug) kwargs.setdefault('validator_list', []).append(validators.isSlug)
# Set db_index=True unless it's been set manually. # Set db_index=True unless it's been set manually.
if 'db_index' not in kwargs: if 'db_index' not in kwargs:
@ -964,7 +995,7 @@ class TimeField(Field):
class URLField(CharField): class URLField(CharField):
def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs): def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
kwargs['maxlength'] = kwargs.get('maxlength', 200) kwargs['max_length'] = kwargs.get('max_length', 200)
if verify_exists: if verify_exists:
kwargs.setdefault('validator_list', []).append(validators.isExistingURL) kwargs.setdefault('validator_list', []).append(validators.isExistingURL)
self.verify_exists = verify_exists self.verify_exists = verify_exists

View File

@ -756,6 +756,9 @@ class ManyToManyField(RelatedField, Field):
"Returns the value of this field in the given model instance." "Returns the value of this field in the given model instance."
return getattr(obj, self.attname).all() return getattr(obj, self.attname).all()
def save_form_data(self, instance, data):
setattr(instance, self.attname, data)
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'form_class': forms.ModelMultipleChoiceField, 'queryset': self.rel.to._default_manager.all()} defaults = {'form_class': forms.ModelMultipleChoiceField, 'queryset': self.rel.to._default_manager.all()}
defaults.update(kwargs) defaults.update(kwargs)

View File

@ -53,7 +53,7 @@ class SelectDateWidget(Widget):
return u'\n'.join(output) return u'\n'.join(output)
def value_from_datadict(self, data, name): def value_from_datadict(self, data, files, name):
y, m, d = data.get(self.year_field % name), data.get(self.month_field % name), data.get(self.day_field % name) y, m, d = data.get(self.year_field % name), data.get(self.month_field % name), data.get(self.day_field % name)
if y and m and d: if y and m and d:
return '%s-%s-%s' % (y, m, d) return '%s-%s-%s' % (y, m, d)

View File

@ -7,10 +7,10 @@ import re
import time import time
from django.utils.translation import ugettext from django.utils.translation import ugettext
from django.utils.encoding import smart_unicode from django.utils.encoding import StrAndUnicode, smart_unicode
from util import ErrorList, ValidationError from util import ErrorList, ValidationError
from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple
try: try:
from decimal import Decimal, DecimalException from decimal import Decimal, DecimalException
@ -22,7 +22,7 @@ __all__ = (
'DEFAULT_DATE_INPUT_FORMATS', 'DateField', 'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
'DEFAULT_TIME_INPUT_FORMATS', 'TimeField', 'DEFAULT_TIME_INPUT_FORMATS', 'TimeField',
'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField', 'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
'RegexField', 'EmailField', 'URLField', 'BooleanField', 'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField', 'BooleanField',
'ChoiceField', 'NullBooleanField', 'MultipleChoiceField', 'ChoiceField', 'NullBooleanField', 'MultipleChoiceField',
'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', 'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
'SplitDateTimeField', 'SplitDateTimeField',
@ -120,6 +120,7 @@ class CharField(Field):
def widget_attrs(self, widget): def widget_attrs(self, widget):
if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)): if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)):
# The HTML attribute is maxlength, not max_length.
return {'maxlength': str(self.max_length)} return {'maxlength': str(self.max_length)}
class IntegerField(Field): class IntegerField(Field):
@ -347,6 +348,55 @@ except ImportError:
# It's OK if Django settings aren't configured. # It's OK if Django settings aren't configured.
URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)' URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
class UploadedFile(StrAndUnicode):
"A wrapper for files uploaded in a FileField"
def __init__(self, filename, content):
self.filename = filename
self.content = content
def __unicode__(self):
"""
The unicode representation is the filename, so that the pre-database-insertion
logic can use UploadedFile objects
"""
return self.filename
class FileField(Field):
widget = FileInput
def __init__(self, *args, **kwargs):
super(FileField, self).__init__(*args, **kwargs)
def clean(self, data):
super(FileField, self).clean(data)
if not self.required and data in EMPTY_VALUES:
return None
try:
f = UploadedFile(data['filename'], data['content'])
except TypeError:
raise ValidationError(ugettext(u"No file was submitted. Check the encoding type on the form."))
except KeyError:
raise ValidationError(ugettext(u"No file was submitted."))
if not f.content:
raise ValidationError(ugettext(u"The submitted file is empty."))
return f
class ImageField(FileField):
def clean(self, data):
"""
Checks that the file-upload field data contains a valid image (GIF, JPG,
PNG, possibly others -- whatever the Python Imaging Library supports).
"""
f = super(ImageField, self).clean(data)
if f is None:
return None
from PIL import Image
from cStringIO import StringIO
try:
Image.open(StringIO(f.content))
except IOError: # Python Imaging Library doesn't recognize it as an image
raise ValidationError(ugettext(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."))
return f
class URLField(RegexField): class URLField(RegexField):
def __init__(self, max_length=None, min_length=None, verify_exists=False, def __init__(self, max_length=None, min_length=None, verify_exists=False,
validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs): validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs):

View File

@ -57,9 +57,10 @@ class BaseForm(StrAndUnicode):
# class is different than Form. See the comments by the Form class for more # class is different than Form. See the comments by the Form class for more
# information. Any improvements to the form API should be made to *this* # information. Any improvements to the form API should be made to *this*
# class, not to the Form class. # class, not to the Form class.
def __init__(self, data=None, auto_id='id_%s', prefix=None, initial=None): def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None):
self.is_bound = data is not None self.is_bound = data is not None or files is not None
self.data = data or {} self.data = data or {}
self.files = files or {}
self.auto_id = auto_id self.auto_id = auto_id
self.prefix = prefix self.prefix = prefix
self.initial = initial or {} self.initial = initial or {}
@ -88,7 +89,7 @@ class BaseForm(StrAndUnicode):
return BoundField(self, field, name) return BoundField(self, field, name)
def _get_errors(self): def _get_errors(self):
"Returns an ErrorDict for self.data" "Returns an ErrorDict for the data provided for the form"
if self._errors is None: if self._errors is None:
self.full_clean() self.full_clean()
return self._errors return self._errors
@ -179,10 +180,10 @@ class BaseForm(StrAndUnicode):
return return
self.cleaned_data = {} self.cleaned_data = {}
for name, field in self.fields.items(): for name, field in self.fields.items():
# value_from_datadict() gets the data from the dictionary. # value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some # Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields. # widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.add_prefix(name)) value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try: try:
value = field.clean(value) value = field.clean(value)
self.cleaned_data[name] = value self.cleaned_data[name] = value
@ -283,7 +284,7 @@ class BoundField(StrAndUnicode):
""" """
Returns the data for this BoundField, or None if it wasn't given. Returns the data for this BoundField, or None if it wasn't given.
""" """
return self.field.widget.value_from_datadict(self.form.data, self.html_name) return self.field.widget.value_from_datadict(self.form.data, self.form.files, self.html_name)
data = property(_data) data = property(_data)
def label_tag(self, contents=None, attrs=None): def label_tag(self, contents=None, attrs=None):

View File

@ -34,18 +34,24 @@ def save_instance(form, instance, fields=None, fail_message='saved', commit=True
continue continue
if fields and f.name not in fields: if fields and f.name not in fields:
continue continue
setattr(instance, f.name, cleaned_data[f.name]) f.save_form_data(instance, cleaned_data[f.name])
if commit: # Wrap up the saving of m2m data as a function
instance.save() def save_m2m():
opts = instance.__class__._meta
cleaned_data = form.cleaned_data
for f in opts.many_to_many: for f in opts.many_to_many:
if fields and f.name not in fields: if fields and f.name not in fields:
continue continue
if f.name in cleaned_data: if f.name in cleaned_data:
setattr(instance, f.attname, cleaned_data[f.name]) f.save_form_data(instance, cleaned_data[f.name])
# GOTCHA: If many-to-many data is given and commit=False, the many-to-many if commit:
# data will be lost. This happens because a many-to-many options cannot be # If we are committing, save the instance and the m2m data immediately
# set on an object until after it's saved. Maybe we should raise an instance.save()
# exception in that case. save_m2m()
else:
# We're not committing. Add a method to the form to allow deferred
# saving of m2m data
form.save_m2m = save_m2m
return instance return instance
def make_model_save(model, fields, fail_message): def make_model_save(model, fields, fail_message):

View File

@ -47,7 +47,7 @@ class Widget(object):
attrs.update(extra_attrs) attrs.update(extra_attrs)
return attrs return attrs
def value_from_datadict(self, data, name): def value_from_datadict(self, data, files, name):
""" """
Given a dictionary of data and this widget's name, returns the value Given a dictionary of data and this widget's name, returns the value
of this widget. Returns None if it's not provided. of this widget. Returns None if it's not provided.
@ -113,7 +113,7 @@ class MultipleHiddenInput(HiddenInput):
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name) final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
return u'\n'.join([(u'<input%s />' % flatatt(dict(value=force_unicode(v), **final_attrs))) for v in value]) return u'\n'.join([(u'<input%s />' % flatatt(dict(value=force_unicode(v), **final_attrs))) for v in value])
def value_from_datadict(self, data, name): def value_from_datadict(self, data, files, name):
if isinstance(data, MultiValueDict): if isinstance(data, MultiValueDict):
return data.getlist(name) return data.getlist(name)
return data.get(name, None) return data.get(name, None)
@ -121,6 +121,13 @@ class MultipleHiddenInput(HiddenInput):
class FileInput(Input): class FileInput(Input):
input_type = 'file' input_type = 'file'
def render(self, name, value, attrs=None):
return super(FileInput, self).render(name, None, attrs=attrs)
def value_from_datadict(self, data, files, name):
"File widgets take data from FILES, not POST"
return files.get(name, None)
class Textarea(Widget): class Textarea(Widget):
def __init__(self, attrs=None): def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness. # The 'rows' and 'cols' attributes are required for HTML correctness.
@ -188,7 +195,7 @@ class NullBooleanSelect(Select):
value = u'1' value = u'1'
return super(NullBooleanSelect, self).render(name, value, attrs, choices) return super(NullBooleanSelect, self).render(name, value, attrs, choices)
def value_from_datadict(self, data, name): def value_from_datadict(self, data, files, name):
value = data.get(name, None) value = data.get(name, None)
return {u'2': True, u'3': False, True: True, False: False}.get(value, None) return {u'2': True, u'3': False, True: True, False: False}.get(value, None)
@ -210,7 +217,7 @@ class SelectMultiple(Widget):
output.append(u'</select>') output.append(u'</select>')
return u'\n'.join(output) return u'\n'.join(output)
def value_from_datadict(self, data, name): def value_from_datadict(self, data, files, name):
if isinstance(data, MultiValueDict): if isinstance(data, MultiValueDict):
return data.getlist(name) return data.getlist(name)
return data.get(name, None) return data.get(name, None)
@ -377,8 +384,8 @@ class MultiWidget(Widget):
return id_ return id_
id_for_label = classmethod(id_for_label) id_for_label = classmethod(id_for_label)
def value_from_datadict(self, data, name): def value_from_datadict(self, data, files, name):
return [widget.value_from_datadict(data, name + '_%s' % i) for i, widget in enumerate(self.widgets)] return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
def format_output(self, rendered_widgets): def format_output(self, rendered_widgets):
""" """

View File

@ -4,6 +4,7 @@ from django.utils.html import escape
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext, ungettext from django.utils.translation import ugettext, ungettext
from django.utils.encoding import smart_unicode, force_unicode from django.utils.encoding import smart_unicode, force_unicode
from django.utils.maxlength import LegacyMaxlength
FORM_FIELD_ID_PREFIX = 'id_' FORM_FIELD_ID_PREFIX = 'id_'
@ -302,6 +303,9 @@ class FormField(object):
Subclasses should also implement a render(data) method, which is responsible Subclasses should also implement a render(data) method, which is responsible
for rending the form field in XHTML. for rending the form field in XHTML.
""" """
# Provide backwards compatibility for the maxlength attribute and
# argument for this class and all subclasses.
__metaclass__ = LegacyMaxlength
def __str__(self): def __str__(self):
return unicode(self).encode('utf-8') return unicode(self).encode('utf-8')
@ -390,19 +394,19 @@ class FormField(object):
class TextField(FormField): class TextField(FormField):
input_type = "text" input_type = "text"
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None, member_name=None): def __init__(self, field_name, length=30, max_length=None, is_required=False, validator_list=None, member_name=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
self.field_name = field_name self.field_name = field_name
self.length, self.maxlength = length, maxlength self.length, self.max_length = length, max_length
self.is_required = is_required self.is_required = is_required
self.validator_list = [self.isValidLength, self.hasNoNewlines] + validator_list self.validator_list = [self.isValidLength, self.hasNoNewlines] + validator_list
if member_name != None: if member_name != None:
self.member_name = member_name self.member_name = member_name
def isValidLength(self, data, form): def isValidLength(self, data, form):
if data and self.maxlength and len(smart_unicode(data)) > self.maxlength: if data and self.max_length and len(smart_unicode(data)) > self.max_length:
raise validators.ValidationError, ungettext("Ensure your text is less than %s character.", raise validators.ValidationError, ungettext("Ensure your text is less than %s character.",
"Ensure your text is less than %s characters.", self.maxlength) % self.maxlength "Ensure your text is less than %s characters.", self.max_length) % self.max_length
def hasNoNewlines(self, data, form): def hasNoNewlines(self, data, form):
if data and '\n' in data: if data and '\n' in data:
@ -411,12 +415,12 @@ class TextField(FormField):
def render(self, data): def render(self, data):
if data is None: if data is None:
data = u'' data = u''
maxlength = u'' max_length = u''
if self.maxlength: if self.max_length:
maxlength = u'maxlength="%s" ' % self.maxlength max_length = u'maxlength="%s" ' % self.max_length
return u'<input type="%s" id="%s" class="v%s%s" name="%s" size="%s" value="%s" %s/>' % \ return u'<input type="%s" id="%s" class="v%s%s" name="%s" size="%s" value="%s" %s/>' % \
(self.input_type, self.get_id(), self.__class__.__name__, self.is_required and u' required' or '', (self.input_type, self.get_id(), self.__class__.__name__, self.is_required and u' required' or '',
self.field_name, self.length, escape(data), maxlength) self.field_name, self.length, escape(data), max_length)
def html2python(data): def html2python(data):
return data return data
@ -426,14 +430,14 @@ class PasswordField(TextField):
input_type = "password" input_type = "password"
class LargeTextField(TextField): class LargeTextField(TextField):
def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, maxlength=None): def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, max_length=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
self.field_name = field_name self.field_name = field_name
self.rows, self.cols, self.is_required = rows, cols, is_required self.rows, self.cols, self.is_required = rows, cols, is_required
self.validator_list = validator_list[:] self.validator_list = validator_list[:]
if maxlength: if max_length:
self.validator_list.append(self.isValidLength) self.validator_list.append(self.isValidLength)
self.maxlength = maxlength self.max_length = max_length
def render(self, data): def render(self, data):
if data is None: if data is None:
@ -710,12 +714,12 @@ class ImageUploadField(FileUploadField):
#################### ####################
class IntegerField(TextField): class IntegerField(TextField):
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None, member_name=None): def __init__(self, field_name, length=10, max_length=None, is_required=False, validator_list=None, member_name=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isInteger] + validator_list validator_list = [self.isInteger] + validator_list
if member_name is not None: if member_name is not None:
self.member_name = member_name self.member_name = member_name
TextField.__init__(self, field_name, length, maxlength, is_required, validator_list) TextField.__init__(self, field_name, length, max_length, is_required, validator_list)
def isInteger(self, field_data, all_data): def isInteger(self, field_data, all_data):
try: try:
@ -730,57 +734,57 @@ class IntegerField(TextField):
html2python = staticmethod(html2python) html2python = staticmethod(html2python)
class SmallIntegerField(IntegerField): class SmallIntegerField(IntegerField):
def __init__(self, field_name, length=5, maxlength=5, is_required=False, validator_list=None): def __init__(self, field_name, length=5, max_length=5, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isSmallInteger] + validator_list validator_list = [self.isSmallInteger] + validator_list
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list) IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
def isSmallInteger(self, field_data, all_data): def isSmallInteger(self, field_data, all_data):
if not -32768 <= int(field_data) <= 32767: if not -32768 <= int(field_data) <= 32767:
raise validators.CriticalValidationError, ugettext("Enter a whole number between -32,768 and 32,767.") raise validators.CriticalValidationError, ugettext("Enter a whole number between -32,768 and 32,767.")
class PositiveIntegerField(IntegerField): class PositiveIntegerField(IntegerField):
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None): def __init__(self, field_name, length=10, max_length=None, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isPositive] + validator_list validator_list = [self.isPositive] + validator_list
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list) IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
def isPositive(self, field_data, all_data): def isPositive(self, field_data, all_data):
if int(field_data) < 0: if int(field_data) < 0:
raise validators.CriticalValidationError, ugettext("Enter a positive number.") raise validators.CriticalValidationError, ugettext("Enter a positive number.")
class PositiveSmallIntegerField(IntegerField): class PositiveSmallIntegerField(IntegerField):
def __init__(self, field_name, length=5, maxlength=None, is_required=False, validator_list=None): def __init__(self, field_name, length=5, max_length=None, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isPositiveSmall] + validator_list validator_list = [self.isPositiveSmall] + validator_list
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list) IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list)
def isPositiveSmall(self, field_data, all_data): def isPositiveSmall(self, field_data, all_data):
if not 0 <= int(field_data) <= 32767: if not 0 <= int(field_data) <= 32767:
raise validators.CriticalValidationError, ugettext("Enter a whole number between 0 and 32,767.") raise validators.CriticalValidationError, ugettext("Enter a whole number between 0 and 32,767.")
class FloatField(TextField): class FloatField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None): def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [validators.isValidFloat] + validator_list validator_list = [validators.isValidFloat] + validator_list
TextField.__init__(self, field_name, is_required=is_required, validator_list=validator_list) TextField.__init__(self, field_name, is_required=is_required, validator_list=validator_list)
def html2python(data): def html2python(data):
if data == '' or data is None: if data == '' or data is None:
return None return None
return float(data) return float(data)
html2python = staticmethod(html2python) html2python = staticmethod(html2python)
class DecimalField(TextField): class DecimalField(TextField):
def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None): def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
self.max_digits, self.decimal_places = max_digits, decimal_places self.max_digits, self.decimal_places = max_digits, decimal_places
validator_list = [self.isValidDecimal] + validator_list validator_list = [self.isValidDecimal] + validator_list
# Initialise the TextField, making sure it's large enough to fit the number with a - sign and a decimal point. # Initialise the TextField, making sure it's large enough to fit the number with a - sign and a decimal point.
super(DecimalField, self).__init__(field_name, max_digits+2, max_digits+2, is_required, validator_list) super(DecimalField, self).__init__(field_name, max_digits+2, max_digits+2, is_required, validator_list)
def isValidDecimal(self, field_data, all_data): def isValidDecimal(self, field_data, all_data):
v = validators.IsValidDecimal(self.max_digits, self.decimal_places) v = validators.IsValidDecimal(self.max_digits, self.decimal_places)
try: try:
v(field_data, all_data) v(field_data, all_data)
except validators.ValidationError, e: except validators.ValidationError, e:
@ -789,14 +793,14 @@ class DecimalField(TextField):
def html2python(data): def html2python(data):
if data == '' or data is None: if data == '' or data is None:
return None return None
try: try:
import decimal import decimal
except ImportError: except ImportError:
from django.utils import _decimal as decimal from django.utils import _decimal as decimal
try: try:
return decimal.Decimal(data) return decimal.Decimal(data)
except decimal.InvalidOperation, e: except decimal.InvalidOperation, e:
raise ValueError, e raise ValueError, e
html2python = staticmethod(html2python) html2python = staticmethod(html2python)
#################### ####################
@ -806,10 +810,10 @@ class DecimalField(TextField):
class DatetimeField(TextField): class DatetimeField(TextField):
"""A FormField that automatically converts its data to a datetime.datetime object. """A FormField that automatically converts its data to a datetime.datetime object.
The data should be in the format YYYY-MM-DD HH:MM:SS.""" The data should be in the format YYYY-MM-DD HH:MM:SS."""
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None): def __init__(self, field_name, length=30, max_length=None, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
self.field_name = field_name self.field_name = field_name
self.length, self.maxlength = length, maxlength self.length, self.max_length = length, max_length
self.is_required = is_required self.is_required = is_required
self.validator_list = [validators.isValidANSIDatetime] + validator_list self.validator_list = [validators.isValidANSIDatetime] + validator_list
@ -836,7 +840,7 @@ class DateField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None): def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isValidDate] + validator_list validator_list = [self.isValidDate] + validator_list
TextField.__init__(self, field_name, length=10, maxlength=10, TextField.__init__(self, field_name, length=10, max_length=10,
is_required=is_required, validator_list=validator_list) is_required=is_required, validator_list=validator_list)
def isValidDate(self, field_data, all_data): def isValidDate(self, field_data, all_data):
@ -861,7 +865,7 @@ class TimeField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None): def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isValidTime] + validator_list validator_list = [self.isValidTime] + validator_list
TextField.__init__(self, field_name, length=8, maxlength=8, TextField.__init__(self, field_name, length=8, max_length=8,
is_required=is_required, validator_list=validator_list) is_required=is_required, validator_list=validator_list)
def isValidTime(self, field_data, all_data): def isValidTime(self, field_data, all_data):
@ -893,10 +897,10 @@ class TimeField(TextField):
class EmailField(TextField): class EmailField(TextField):
"A convenience FormField for validating e-mail addresses" "A convenience FormField for validating e-mail addresses"
def __init__(self, field_name, length=50, maxlength=75, is_required=False, validator_list=None): def __init__(self, field_name, length=50, max_length=75, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isValidEmail] + validator_list validator_list = [self.isValidEmail] + validator_list
TextField.__init__(self, field_name, length, maxlength=maxlength, TextField.__init__(self, field_name, length, max_length=max_length,
is_required=is_required, validator_list=validator_list) is_required=is_required, validator_list=validator_list)
def isValidEmail(self, field_data, all_data): def isValidEmail(self, field_data, all_data):
@ -907,10 +911,10 @@ class EmailField(TextField):
class URLField(TextField): class URLField(TextField):
"A convenience FormField for validating URLs" "A convenience FormField for validating URLs"
def __init__(self, field_name, length=50, maxlength=200, is_required=False, validator_list=None): def __init__(self, field_name, length=50, max_length=200, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isValidURL] + validator_list validator_list = [self.isValidURL] + validator_list
TextField.__init__(self, field_name, length=length, maxlength=maxlength, TextField.__init__(self, field_name, length=length, max_length=max_length,
is_required=is_required, validator_list=validator_list) is_required=is_required, validator_list=validator_list)
def isValidURL(self, field_data, all_data): def isValidURL(self, field_data, all_data):
@ -920,10 +924,10 @@ class URLField(TextField):
raise validators.CriticalValidationError, e.messages raise validators.CriticalValidationError, e.messages
class IPAddressField(TextField): class IPAddressField(TextField):
def __init__(self, field_name, length=15, maxlength=15, is_required=False, validator_list=None): def __init__(self, field_name, length=15, max_length=15, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isValidIPAddress] + validator_list validator_list = [self.isValidIPAddress] + validator_list
TextField.__init__(self, field_name, length=length, maxlength=maxlength, TextField.__init__(self, field_name, length=length, max_length=max_length,
is_required=is_required, validator_list=validator_list) is_required=is_required, validator_list=validator_list)
def isValidIPAddress(self, field_data, all_data): def isValidIPAddress(self, field_data, all_data):
@ -970,7 +974,7 @@ class PhoneNumberField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None): def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isValidPhone] + validator_list validator_list = [self.isValidPhone] + validator_list
TextField.__init__(self, field_name, length=12, maxlength=12, TextField.__init__(self, field_name, length=12, max_length=12,
is_required=is_required, validator_list=validator_list) is_required=is_required, validator_list=validator_list)
def isValidPhone(self, field_data, all_data): def isValidPhone(self, field_data, all_data):
@ -984,7 +988,7 @@ class USStateField(TextField):
def __init__(self, field_name, is_required=False, validator_list=None): def __init__(self, field_name, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isValidUSState] + validator_list validator_list = [self.isValidUSState] + validator_list
TextField.__init__(self, field_name, length=2, maxlength=2, TextField.__init__(self, field_name, length=2, max_length=2,
is_required=is_required, validator_list=validator_list) is_required=is_required, validator_list=validator_list)
def isValidUSState(self, field_data, all_data): def isValidUSState(self, field_data, all_data):
@ -1001,10 +1005,10 @@ class USStateField(TextField):
class CommaSeparatedIntegerField(TextField): class CommaSeparatedIntegerField(TextField):
"A convenience FormField for validating comma-separated integer fields" "A convenience FormField for validating comma-separated integer fields"
def __init__(self, field_name, maxlength=None, is_required=False, validator_list=None): def __init__(self, field_name, max_length=None, is_required=False, validator_list=None):
if validator_list is None: validator_list = [] if validator_list is None: validator_list = []
validator_list = [self.isCommaSeparatedIntegerList] + validator_list validator_list = [self.isCommaSeparatedIntegerList] + validator_list
TextField.__init__(self, field_name, length=20, maxlength=maxlength, TextField.__init__(self, field_name, length=20, max_length=max_length,
is_required=is_required, validator_list=validator_list) is_required=is_required, validator_list=validator_list)
def isCommaSeparatedIntegerList(self, field_data, all_data): def isCommaSeparatedIntegerList(self, field_data, all_data):

View File

@ -649,8 +649,8 @@ def do_if(parser, token):
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
will be displayed if the test fails. will be displayed if the test fails.
``if`` tags may use ``or`` or ``not`` to test a number of variables or to ``if`` tags may use ``or``, ``and`` or ``not`` to test a number of
negate a given variable:: variables or to negate a given variable::
{% if not athlete_list %} {% if not athlete_list %}
There are no athletes. There are no athletes.
@ -660,19 +660,32 @@ def do_if(parser, token):
There are some athletes or some coaches. There are some athletes or some coaches.
{% endif %} {% endif %}
{% if athlete_list and coach_list %}
Both atheletes and coaches are available.
{% endif %}
{% if not athlete_list or coach_list %} {% if not athlete_list or coach_list %}
There are no athletes, or there are some coaches. There are no athletes, or there are some coaches.
{% endif %} {% endif %}
For simplicity, ``if`` tags do not allow ``and`` clauses. Use nested ``if`` {% if athlete_list and not coach_list %}
tags instead:: There are some athletes and absolutely no coaches.
{% if athlete_list %}
{% if coach_list %}
Number of athletes: {{ athlete_list|count }}.
Number of coaches: {{ coach_list|count }}.
{% endif %}
{% endif %} {% endif %}
``if`` tags do not allow ``and`` and ``or`` clauses with the same
tag, because the order of logic would be ambigous. For example,
this is invalid::
{% if athlete_list and coach_list or cheerleader_list %}
If you need to combine and and or to do advanced logic, just use
nested if tags. For example:
{% if athlete_list %}
{% if coach_list or cheerleader_list %}
We have athletes, and either coaches or cheerleaders!
{% endif %}
{% endif %}
""" """
bits = token.contents.split() bits = token.contents.split()
del bits[0] del bits[0]

View File

@ -1,6 +1,5 @@
import types import types
import urllib import urllib
from django.conf import settings
from django.utils.functional import Promise from django.utils.functional import Promise
class StrAndUnicode(object): class StrAndUnicode(object):

67
django/utils/maxlength.py Normal file
View File

@ -0,0 +1,67 @@
"""
Utilities for providing backwards compatibility for the maxlength argument,
which has been replaced by max_length, see ticket #2101.
"""
from warnings import warn
def get_maxlength(self):
return self.max_length
def set_maxlength(self, value):
self.max_length = value
def legacy_maxlength(max_length, maxlength):
"""
Consolidates max_length and maxlength, providing backwards compatibilty
for the legacy "maxlength" argument.
If one of max_length or maxlength is given, then that value is returned.
If both are given, a TypeError is raised.
If maxlength is used at all, a deprecation warning is issued.
"""
if maxlength is not None:
warn("maxlength is deprecated, use max_length instead.",
PendingDeprecationWarning,
stacklevel=3)
if max_length is not None:
raise TypeError("field can not take both the max_length"
" argument and the legacy maxlength argument.")
max_length = maxlength
return max_length
def remove_maxlength(func):
"""
A decorator to be used on a class's __init__ that provides backwards
compatibilty for the legacy "maxlength" keyword argument, i.e.
name = models.CharField(maxlength=20)
It does this by changing the passed "maxlength" keyword argument
(if it exists) into a "max_length" keyword argument.
"""
def inner(self, *args, **kwargs):
max_length = kwargs.get('max_length', None)
# pop maxlength because we don't want this going to __init__.
maxlength = kwargs.pop('maxlength', None)
max_length = legacy_maxlength(max_length, maxlength)
# Only set the max_length keyword argument if we got a value back.
if max_length is not None:
kwargs['max_length'] = max_length
func(self, *args, **kwargs)
return inner
# This metaclass is used in two places, and should be removed when legacy
# support for maxlength is dropped.
# * oldforms.FormField
# * db.models.fields.Field
class LegacyMaxlength(type):
"""
Metaclass for providing backwards compatibility support for the
"maxlength" keyword argument.
"""
def __init__(cls, name, bases, attrs):
super(LegacyMaxlength, cls).__init__(name, bases, attrs)
# Decorate the class's __init__ to remove any maxlength keyword.
cls.__init__ = remove_maxlength(cls.__init__)
# Support accessing and setting to the legacy maxlength attribute.
cls.maxlength = property(get_maxlength, set_maxlength)

View File

@ -214,7 +214,7 @@ A framework for generating syndication feeds, in RSS and Atom, quite easily.
See the `syndication documentation`_. See the `syndication documentation`_.
.. _syndication documentation: ../syndication/ .. _syndication documentation: ../syndication_feeds/
Other add-ons Other add-ons
============= =============

View File

@ -82,9 +82,6 @@ that 90% of Django can be considered forwards-compatible at this point.
That said, these APIs should *not* be considered stable, and are likely to That said, these APIs should *not* be considered stable, and are likely to
change: change:
- `Forms and validation`_ will most likely be completely rewritten to
deemphasize Manipulators in favor of validation-aware models.
- `Serialization`_ is under heavy development; changes are likely. - `Serialization`_ is under heavy development; changes are likely.
- The `authentication`_ framework is changing to be far more flexible, and - The `authentication`_ framework is changing to be far more flexible, and
@ -114,7 +111,7 @@ change:
.. _sending email: ../email/ .. _sending email: ../email/
.. _sessions: ../sessions/ .. _sessions: ../sessions/
.. _settings: ../settings/ .. _settings: ../settings/
.. _syndication: ../syndication/ .. _syndication: ../syndication_feeds/
.. _template language: ../templates/ .. _template language: ../templates/
.. _transactions: ../transactions/ .. _transactions: ../transactions/
.. _url dispatch: ../url_dispatch/ .. _url dispatch: ../url_dispatch/

View File

@ -234,7 +234,7 @@ the setting and checking of these values behind the scenes.
Previous Django versions, such as 0.90, used simple MD5 hashes without password Previous Django versions, such as 0.90, used simple MD5 hashes without password
salts. For backwards compatibility, those are still supported; they'll be salts. For backwards compatibility, those are still supported; they'll be
converted automatically to the new style the first time ``check_password()`` converted automatically to the new style the first time ``User.check_password()``
works correctly for a given user. works correctly for a given user.
Anonymous users Anonymous users

View File

@ -340,14 +340,14 @@ Model style
Do this:: Do this::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=20) first_name = models.CharField(max_length=20)
last_name = models.CharField(maxlength=40) last_name = models.CharField(max_length=40)
Don't do this:: Don't do this::
class Person(models.Model): class Person(models.Model):
FirstName = models.CharField(maxlength=20) FirstName = models.CharField(max_length=20)
Last_Name = models.CharField(maxlength=40) Last_Name = models.CharField(max_length=40)
* The ``class Meta`` should appear *after* the fields are defined, with * The ``class Meta`` should appear *after* the fields are defined, with
a single blank line separating the fields and the class definition. a single blank line separating the fields and the class definition.
@ -355,8 +355,8 @@ Model style
Do this:: Do this::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=20) first_name = models.CharField(max_length=20)
last_name = models.CharField(maxlength=40) last_name = models.CharField(max_length=40)
class Meta: class Meta:
verbose_name_plural = 'people' verbose_name_plural = 'people'
@ -364,8 +364,8 @@ Model style
Don't do this:: Don't do this::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=20) first_name = models.CharField(max_length=20)
last_name = models.CharField(maxlength=40) last_name = models.CharField(max_length=40)
class Meta: class Meta:
verbose_name_plural = 'people' verbose_name_plural = 'people'
@ -375,8 +375,8 @@ Model style
class Meta: class Meta:
verbose_name_plural = 'people' verbose_name_plural = 'people'
first_name = models.CharField(maxlength=20) first_name = models.CharField(max_length=20)
last_name = models.CharField(maxlength=40) last_name = models.CharField(max_length=40)
* The order of model inner classes and standard methods should be as * The order of model inner classes and standard methods should be as
follows (noting that these are not all required): follows (noting that these are not all required):

View File

@ -124,7 +124,7 @@ Several other MySQLdb connection options may be useful, such as ``ssl``,
``use_unicode``, ``init_command``, and ``sql_mode``. Consult the ``use_unicode``, ``init_command``, and ``sql_mode``. Consult the
`MySQLdb documentation`_ for more details. `MySQLdb documentation`_ for more details.
.. _settings documentation: http://www.djangoproject.com/documentation/settings/#database-engine .. _settings documentation: ../settings/#database-engine
.. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html .. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html
.. _MySQLdb documentation: http://mysql-python.sourceforge.net/ .. _MySQLdb documentation: http://mysql-python.sourceforge.net/

View File

@ -12,14 +12,14 @@ Throughout this reference, we'll refer to the following models, which comprise
a weblog application:: a weblog application::
class Blog(models.Model): class Blog(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
tagline = models.TextField() tagline = models.TextField()
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Author(models.Model): class Author(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
email = models.EmailField() email = models.EmailField()
def __unicode__(self): def __unicode__(self):
@ -27,7 +27,7 @@ a weblog application::
class Entry(models.Model): class Entry(models.Model):
blog = models.ForeignKey(Blog) blog = models.ForeignKey(Blog)
headline = models.CharField(maxlength=255) headline = models.CharField(max_length=255)
body_text = models.TextField() body_text = models.TextField()
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
authors = models.ManyToManyField(Author) authors = models.ManyToManyField(Author)
@ -1503,7 +1503,7 @@ precede the definition of any keyword arguments. For example::
See the `OR lookups examples page`_ for more examples. See the `OR lookups examples page`_ for more examples.
.. _OR lookups examples page: http://www.djangoproject.com/documentation/models/or_lookups/ .. _OR lookups examples page: ../models/or_lookups/
Related objects Related objects
=============== ===============
@ -1806,8 +1806,8 @@ following model::
('F', 'Female'), ('F', 'Female'),
) )
class Person(models.Model): class Person(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES) gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
...each ``Person`` instance will have a ``get_gender_display()`` method. Example:: ...each ``Person`` instance will have a ``get_gender_display()`` method. Example::
@ -1834,7 +1834,7 @@ Note that in the case of identical date values, these methods will use the ID
as a fallback check. This guarantees that no records are skipped or duplicated. as a fallback check. This guarantees that no records are skipped or duplicated.
For a full example, see the `lookup API sample model`_. For a full example, see the `lookup API sample model`_.
.. _lookup API sample model: http://www.djangoproject.com/documentation/models/lookup/ .. _lookup API sample model: ../models/lookup/
get_FOO_filename() get_FOO_filename()
------------------ ------------------

View File

@ -314,7 +314,7 @@ To send a text and HTML combination, you could write::
subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
text_content = 'This is an important message.' text_content = 'This is an important message.'
html_content = '<p>This is an <strong>important</strong> message.' html_content = '<p>This is an <strong>important</strong> message.</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, to) msg = EmailMultiAlternatives(subject, text_content, from_email, to)
msg.attach_alternative(html_content, "text/html") msg.attach_alternative(html_content, "text/html")
msg.send() msg.send()

View File

@ -42,7 +42,10 @@ Listen to his music. You'll like it.
Django is pronounced **JANG**-oh. Rhymes with FANG-oh. The "D" is silent. Django is pronounced **JANG**-oh. Rhymes with FANG-oh. The "D" is silent.
We've also recorded an `audio clip of the pronunciation`_.
.. _Django Reinhardt: http://en.wikipedia.org/wiki/Django_Reinhardt .. _Django Reinhardt: http://en.wikipedia.org/wiki/Django_Reinhardt
.. _audio clip of the pronunciation: http://red-bean.com/~adrian/django_pronunciation.mp3
Is Django stable? Is Django stable?
----------------- -----------------

View File

@ -37,11 +37,11 @@ this document, we'll be working with the following model, a "place" object::
) )
class Place(models.Model): class Place(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
address = models.CharField(maxlength=100, blank=True) address = models.CharField(max_length=100, blank=True)
city = models.CharField(maxlength=50, blank=True) city = models.CharField(max_length=50, blank=True)
state = models.USStateField() state = models.USStateField()
zip_code = models.CharField(maxlength=5, blank=True) zip_code = models.CharField(max_length=5, blank=True)
place_type = models.IntegerField(choices=PLACE_TYPES) place_type = models.IntegerField(choices=PLACE_TYPES)
class Admin: class Admin:
@ -388,7 +388,7 @@ for a "contact" form on a website::
def __init__(self): def __init__(self):
self.fields = ( self.fields = (
forms.EmailField(field_name="from", is_required=True), forms.EmailField(field_name="from", is_required=True),
forms.TextField(field_name="subject", length=30, maxlength=200, is_required=True), forms.TextField(field_name="subject", length=30, max_length=200, is_required=True),
forms.SelectField(field_name="urgency", choices=urgency_choices), forms.SelectField(field_name="urgency", choices=urgency_choices),
forms.LargeTextField(field_name="contents", is_required=True), forms.LargeTextField(field_name="contents", is_required=True),
) )

View File

@ -22,7 +22,7 @@ A companion to this document is the `official repository of model examples`_.
``tests/modeltests`` directory.) ``tests/modeltests`` directory.)
.. _Database API reference: ../db-api/ .. _Database API reference: ../db-api/
.. _official repository of model examples: http://www.djangoproject.com/documentation/models/ .. _official repository of model examples: ../models/
Quick example Quick example
============= =============
@ -33,8 +33,8 @@ This example model defines a ``Person``, which has a ``first_name`` and
from django.db import models from django.db import models
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(maxlength=30) last_name = models.CharField(max_length=30)
``first_name`` and ``last_name`` are *fields* of the model. Each field is ``first_name`` and ``last_name`` are *fields* of the model. Each field is
specified as a class attribute, and each attribute maps to a database column. specified as a class attribute, and each attribute maps to a database column.
@ -69,13 +69,13 @@ attributes.
Example:: Example::
class Musician(models.Model): class Musician(models.Model):
first_name = models.CharField(maxlength=50) first_name = models.CharField(max_length=50)
last_name = models.CharField(maxlength=50) last_name = models.CharField(max_length=50)
instrument = models.CharField(maxlength=100) instrument = models.CharField(max_length=100)
class Album(models.Model): class Album(models.Model):
artist = models.ForeignKey(Musician) artist = models.ForeignKey(Musician)
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
release_date = models.DateField() release_date = models.DateField()
num_stars = models.IntegerField() num_stars = models.IntegerField()
@ -142,14 +142,18 @@ For large amounts of text, use ``TextField``.
The admin represents this as an ``<input type="text">`` (a single-line input). The admin represents this as an ``<input type="text">`` (a single-line input).
``CharField`` has an extra required argument, ``maxlength``, the maximum length ``CharField`` has an extra required argument, ``max_length``, the maximum length
(in characters) of the field. The maxlength is enforced at the database level (in characters) of the field. The max_length is enforced at the database level
and in Django's validation. and in Django's validation.
``CommaSeparatedIntegerField`` Django veterans: Note that the argument is now called ``max_length`` to
provide consistency throughout Django. There is full legacy support for
the old ``maxlength`` argument, but ``max_length`` is prefered.
``CommaSeparatedIntegerField``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A field of integers separated by commas. As in ``CharField``, the ``maxlength`` A field of integers separated by commas. As in ``CharField``, the ``max_length``
argument is required. argument is required.
``DateField`` ``DateField``
@ -217,7 +221,7 @@ The admin represents this as an ``<input type="text">`` (a single-line input).
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
A ``CharField`` that checks that the value is a valid e-mail address. A ``CharField`` that checks that the value is a valid e-mail address.
This doesn't accept ``maxlength``; its ``maxlength`` is automatically set to This doesn't accept ``max_length``; its ``max_length`` is automatically set to
75. 75.
``FileField`` ``FileField``
@ -400,7 +404,7 @@ Like a ``PositiveIntegerField``, but only allows values under a certain
containing only letters, numbers, underscores or hyphens. They're generally containing only letters, numbers, underscores or hyphens. They're generally
used in URLs. used in URLs.
Like a CharField, you can specify ``maxlength``. If ``maxlength`` is Like a CharField, you can specify ``max_length``. If ``max_length`` is
not specified, Django will use a default length of 50. not specified, Django will use a default length of 50.
Implies ``db_index=True``. Implies ``db_index=True``.
@ -447,9 +451,9 @@ and doesn't give a 404 response).
The admin represents this as an ``<input type="text">`` (a single-line input). The admin represents this as an ``<input type="text">`` (a single-line input).
``URLField`` takes an optional argument, ``maxlength``, the maximum length (in ``URLField`` takes an optional argument, ``max_length``, the maximum length (in
characters) of the field. The maxlength is enforced at the database level and characters) of the field. The maximum length is enforced at the database level and
in Django's validation. If you don't specify ``maxlength``, a default of 200 in Django's validation. If you don't specify ``max_length``, a default of 200
is used. is used.
``USStateField`` ``USStateField``
@ -536,7 +540,7 @@ The choices list can be defined either as part of your model class::
('M', 'Male'), ('M', 'Male'),
('F', 'Female'), ('F', 'Female'),
) )
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES) gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
or outside your model class altogether:: or outside your model class altogether::
@ -545,7 +549,7 @@ or outside your model class altogether::
('F', 'Female'), ('F', 'Female'),
) )
class Foo(models.Model): class Foo(models.Model):
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES) gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
For each model field that has ``choices`` set, Django will add a method to For each model field that has ``choices`` set, Django will add a method to
retrieve the human-readable name for the field's current value. See retrieve the human-readable name for the field's current value. See
@ -620,6 +624,12 @@ Extra "help" text to be displayed under the field on the object's admin
form. It's useful for documentation even if your object doesn't have an form. It's useful for documentation even if your object doesn't have an
admin form. admin form.
Note that this value is *not* HTML-escaped when it's displayed in the admin
interface. This lets you include HTML in ``help_text`` if you so desire. For
example::
help_text="Please use the following format: <em>YYYY-MM-DD</em>."
``primary_key`` ``primary_key``
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
@ -698,11 +708,11 @@ it using the field's attribute name, converting underscores to spaces.
In this example, the verbose name is ``"Person's first name"``:: In this example, the verbose name is ``"Person's first name"``::
first_name = models.CharField("Person's first name", maxlength=30) first_name = models.CharField("Person's first name", max_length=30)
In this example, the verbose name is ``"first name"``:: In this example, the verbose name is ``"first name"``::
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
``ForeignKey``, ``ManyToManyField`` and ``OneToOneField`` require the first ``ForeignKey``, ``ManyToManyField`` and ``OneToOneField`` require the first
argument to be a model class, so use the ``verbose_name`` keyword argument:: argument to be a model class, so use the ``verbose_name`` keyword argument::
@ -775,7 +785,7 @@ You can, of course, call the field whatever you want. For example::
See the `Many-to-one relationship model example`_ for a full example. See the `Many-to-one relationship model example`_ for a full example.
.. _Many-to-one relationship model example: http://www.djangoproject.com/documentation/models/many_to_one/ .. _Many-to-one relationship model example: ../models/many_to_one/
``ForeignKey`` fields take a number of extra arguments for defining how the ``ForeignKey`` fields take a number of extra arguments for defining how the
relationship should work. All are optional: relationship should work. All are optional:
@ -902,7 +912,7 @@ set up above, the ``Pizza`` admin form would let users select the toppings.
See the `Many-to-many relationship model example`_ for a full example. See the `Many-to-many relationship model example`_ for a full example.
.. _Many-to-many relationship model example: http://www.djangoproject.com/documentation/models/many_to_many/ .. _Many-to-many relationship model example: ../models/many_to_many/
``ManyToManyField`` objects take a number of extra arguments for defining how ``ManyToManyField`` objects take a number of extra arguments for defining how
the relationship should work. All are optional: the relationship should work. All are optional:
@ -979,7 +989,7 @@ as a read-only field when you edit an object in the admin interface:
See the `One-to-one relationship model example`_ for a full example. See the `One-to-one relationship model example`_ for a full example.
.. _One-to-one relationship model example: http://www.djangoproject.com/documentation/models/one_to_one/ .. _One-to-one relationship model example: ../models/one_to_one/
Custom field types Custom field types
------------------ ------------------
@ -1027,8 +1037,8 @@ Once you have ``MytypeField``, you can use it in any model, just like any other
``Field`` type:: ``Field`` type::
class Person(models.Model): class Person(models.Model):
name = models.CharField(maxlength=80) name = models.CharField(max_length=80)
gender = models.CharField(maxlength=1) gender = models.CharField(max_length=1)
something_else = MytypeField() something_else = MytypeField()
If you aim to build a database-agnostic application, you should account for If you aim to build a database-agnostic application, you should account for
@ -1074,12 +1084,12 @@ time -- i.e., when the class is instantiated. To do that, just implement
# This is a much more flexible example. # This is a much more flexible example.
class BetterCharField(models.Field): class BetterCharField(models.Field):
def __init__(self, maxlength, *args, **kwargs): def __init__(self, max_length, *args, **kwargs):
self.maxlength = maxlength self.max_length = max_length
super(BetterCharField, self).__init__(*args, **kwargs) super(BetterCharField, self).__init__(*args, **kwargs)
def db_type(self): def db_type(self):
return 'char(%s)' % self.maxlength return 'char(%s)' % self.max_length
# In the model: # In the model:
class MyModel(models.Model): class MyModel(models.Model):
@ -1096,7 +1106,7 @@ Meta options
Give your model metadata by using an inner ``class Meta``, like so:: Give your model metadata by using an inner ``class Meta``, like so::
class Foo(models.Model): class Foo(models.Model):
bar = models.CharField(maxlength=30) bar = models.CharField(max_length=30)
class Meta: class Meta:
# ... # ...
@ -1186,7 +1196,7 @@ See `Specifying ordering`_ for more examples.
Note that, regardless of how many fields are in ``ordering``, the admin Note that, regardless of how many fields are in ``ordering``, the admin
site uses only the first field. site uses only the first field.
.. _Specifying ordering: http://www.djangoproject.com/documentation/models/ordering/ .. _Specifying ordering: ../models/ordering/
``permissions`` ``permissions``
--------------- ---------------
@ -1270,8 +1280,8 @@ If you want your model to be visible to Django's admin site, give your model an
inner ``"class Admin"``, like so:: inner ``"class Admin"``, like so::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(maxlength=30) last_name = models.CharField(max_length=30)
class Admin: class Admin:
# Admin options go here # Admin options go here
@ -1430,7 +1440,7 @@ A few special cases to note about ``list_display``:
Here's a full example model:: Here's a full example model::
class Person(models.Model): class Person(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
birthday = models.DateField() birthday = models.DateField()
class Admin: class Admin:
@ -1447,9 +1457,9 @@ A few special cases to note about ``list_display``:
Here's a full example model:: Here's a full example model::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=50) first_name = models.CharField(max_length=50)
last_name = models.CharField(maxlength=50) last_name = models.CharField(max_length=50)
color_code = models.CharField(maxlength=6) color_code = models.CharField(max_length=6)
class Admin: class Admin:
list_display = ('first_name', 'last_name', 'colored_name') list_display = ('first_name', 'last_name', 'colored_name')
@ -1465,7 +1475,7 @@ A few special cases to note about ``list_display``:
Here's a full example model:: Here's a full example model::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=50) first_name = models.CharField(max_length=50)
birthday = models.DateField() birthday = models.DateField()
class Admin: class Admin:
@ -1493,8 +1503,8 @@ A few special cases to note about ``list_display``:
For example:: For example::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=50) first_name = models.CharField(max_length=50)
color_code = models.CharField(maxlength=6) color_code = models.CharField(max_length=6)
class Admin: class Admin:
list_display = ('first_name', 'colored_first_name') list_display = ('first_name', 'colored_first_name')
@ -1744,13 +1754,13 @@ returns a list of all ``OpinionPoll`` objects, each with an extra
return result_list return result_list
class OpinionPoll(models.Model): class OpinionPoll(models.Model):
question = models.CharField(maxlength=200) question = models.CharField(max_length=200)
poll_date = models.DateField() poll_date = models.DateField()
objects = PollManager() objects = PollManager()
class Response(models.Model): class Response(models.Model):
poll = models.ForeignKey(Poll) poll = models.ForeignKey(Poll)
person_name = models.CharField(maxlength=50) person_name = models.CharField(max_length=50)
response = models.TextField() response = models.TextField()
With this example, you'd use ``OpinionPoll.objects.with_counts()`` to return With this example, you'd use ``OpinionPoll.objects.with_counts()`` to return
@ -1766,8 +1776,8 @@ A ``Manager``'s base ``QuerySet`` returns all objects in the system. For
example, using this model:: example, using this model::
class Book(models.Model): class Book(models.Model):
title = models.CharField(maxlength=100) title = models.CharField(max_length=100)
author = models.CharField(maxlength=50) author = models.CharField(max_length=50)
...the statement ``Book.objects.all()`` will return all books in the database. ...the statement ``Book.objects.all()`` will return all books in the database.
@ -1785,8 +1795,8 @@ all objects, and one that returns only the books by Roald Dahl::
# Then hook it into the Book model explicitly. # Then hook it into the Book model explicitly.
class Book(models.Model): class Book(models.Model):
title = models.CharField(maxlength=100) title = models.CharField(max_length=100)
author = models.CharField(maxlength=50) author = models.CharField(max_length=50)
objects = models.Manager() # The default manager. objects = models.Manager() # The default manager.
dahl_objects = DahlBookManager() # The Dahl-specific manager. dahl_objects = DahlBookManager() # The Dahl-specific manager.
@ -1819,9 +1829,9 @@ For example::
return super(FemaleManager, self).get_query_set().filter(sex='F') return super(FemaleManager, self).get_query_set().filter(sex='F')
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=50) first_name = models.CharField(max_length=50)
last_name = models.CharField(maxlength=50) last_name = models.CharField(max_length=50)
sex = models.CharField(maxlength=1, choices=(('M', 'Male'), ('F', 'Female'))) sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
people = models.Manager() people = models.Manager()
men = MaleManager() men = MaleManager()
women = FemaleManager() women = FemaleManager()
@ -1851,11 +1861,11 @@ model.
For example, this model has a few custom methods:: For example, this model has a few custom methods::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=50) first_name = models.CharField(max_length=50)
last_name = models.CharField(maxlength=50) last_name = models.CharField(max_length=50)
birth_date = models.DateField() birth_date = models.DateField()
address = models.CharField(maxlength=100) address = models.CharField(max_length=100)
city = models.CharField(maxlength=50) city = models.CharField(max_length=50)
state = models.USStateField() # Yes, this is America-centric... state = models.USStateField() # Yes, this is America-centric...
def baby_boomer_status(self): def baby_boomer_status(self):
@ -1897,8 +1907,8 @@ Although this isn't required, it's strongly encouraged (see the description of
For example:: For example::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=50) first_name = models.CharField(max_length=50)
last_name = models.CharField(maxlength=50) last_name = models.CharField(max_length=50)
def __str__(self): def __str__(self):
# Note use of django.utils.encoding.smart_str() here because # Note use of django.utils.encoding.smart_str() here because
@ -1915,8 +1925,8 @@ method for your model. The example in the previous section could be written
more simply as:: more simply as::
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=50) first_name = models.CharField(max_length=50)
last_name = models.CharField(maxlength=50) last_name = models.CharField(max_length=50)
def __unicode__(self): def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name) return u'%s %s' % (self.first_name, self.last_name)
@ -1942,10 +1952,12 @@ Django uses this in its admin interface. If an object defines
link that will jump you directly to the object's public view, according to link that will jump you directly to the object's public view, according to
``get_absolute_url()``. ``get_absolute_url()``.
Also, a couple of other bits of Django, such as the syndication-feed framework, Also, a couple of other bits of Django, such as the `syndication feed framework`_,
use ``get_absolute_url()`` as a convenience to reward people who've defined the use ``get_absolute_url()`` as a convenience to reward people who've defined the
method. method.
.. syndication feed framework: ../syndication_feeds/
It's good practice to use ``get_absolute_url()`` in templates, instead of It's good practice to use ``get_absolute_url()`` in templates, instead of
hard-coding your objects' URLs. For example, this template code is bad:: hard-coding your objects' URLs. For example, this template code is bad::
@ -2056,7 +2068,7 @@ A classic use-case for overriding the built-in methods is if you want something
to happen whenever you save an object. For example:: to happen whenever you save an object. For example::
class Blog(models.Model): class Blog(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
tagline = models.TextField() tagline = models.TextField()
def save(self): def save(self):
@ -2067,7 +2079,7 @@ to happen whenever you save an object. For example::
You can also prevent saving:: You can also prevent saving::
class Blog(models.Model): class Blog(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
tagline = models.TextField() tagline = models.TextField()
def save(self): def save(self):

View File

@ -641,7 +641,7 @@ the "Outputting forms as HTML" section above.
The simplest way to display a form's HTML is to use the variable on its own, The simplest way to display a form's HTML is to use the variable on its own,
like this:: like this::
<form method="post"> <form method="post" action="">
<table>{{ form }}</table> <table>{{ form }}</table>
<input type="submit" /> <input type="submit" />
</form> </form>
@ -653,7 +653,7 @@ class' ``__str__()`` method calls its ``as_table()`` method.
The following is equivalent but a bit more explicit:: The following is equivalent but a bit more explicit::
<form method="post"> <form method="post" action="">
<table>{{ form.as_table }}</table> <table>{{ form.as_table }}</table>
<input type="submit" /> <input type="submit" />
</form> </form>
@ -675,7 +675,7 @@ individual fields for complete template control over the form's design.
The easiest way is to iterate over the form's fields, with The easiest way is to iterate over the form's fields, with
``{% for field in form %}``. For example:: ``{% for field in form %}``. For example::
<form method="post"> <form method="post" action="">
<dl> <dl>
{% for field in form %} {% for field in form %}
<dt>{{ field.label }}</dt> <dt>{{ field.label }}</dt>
@ -696,7 +696,7 @@ Alternatively, you can arrange the form's fields explicitly, by name. Do that
by accessing ``{{ form.fieldname }}``, where ``fieldname`` is the field's name. by accessing ``{{ form.fieldname }}``, where ``fieldname`` is the field's name.
For example:: For example::
<form method="post"> <form method="post" action="">
<ul class="myformclass"> <ul class="myformclass">
<li>{{ form.sender.label }} {{ form.sender }}</li> <li>{{ form.sender.label }} {{ form.sender }}</li>
<li class="helptext">{{ form.sender.help_text }}</li> <li class="helptext">{{ form.sender.help_text }}</li>
@ -710,6 +710,49 @@ For example::
</ul> </ul>
</form> </form>
Binding uploaded files to a form
--------------------------------
**New in Django development version**
Dealing with forms that have ``FileField`` and ``ImageField`` fields
is a little more complicated than a normal form.
Firstly, in order to upload files, you'll need to make sure that your
``<form>`` element correctly defines the ``enctype`` as
``"multipart/form-data"``::
<form enctype="multipart/form-data" method="post" action="/foo/">
Secondly, when you use the form, you need to bind the file data. File
data is handled separately to normal form data, so when your form
contains a ``FileField`` and ``ImageField``, you will need to specify
a second argument when you bind your form. So if we extend our
ContactForm to include an ``ImageField`` called ``mugshot``, we
need to bind the file data containing the mugshot image::
# Bound form with an image field
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': 'foo@example.com',
... 'cc_myself': True}
>>> file_data = {'mugshot': {'filename':'face.jpg'
... 'content': <file data>}}
>>> f = ContactFormWithMugshot(data, file_data)
In practice, you will usually specify ``request.FILES`` as the source
of file data (just like you use ``request.POST`` as the source of
form data)::
# Bound form with an image field, data from the request
>>> f = ContactFormWithMugshot(request.POST, request.FILES)
Constructing an unbound form is the same as always -- just omit both
form data *and* file data:
# Unbound form with a image field
>>> f = ContactFormWithMugshot()
Subclassing forms Subclassing forms
----------------- -----------------
@ -1099,6 +1142,54 @@ Has two optional arguments for validation, ``max_length`` and ``min_length``.
If provided, these arguments ensure that the string is at most or at least the If provided, these arguments ensure that the string is at most or at least the
given length. given length.
``FileField``
~~~~~~~~~~~~~
**New in Django development version**
* Default widget: ``FileInput``
* Empty value: ``None``
* Normalizes to: An ``UploadedFile`` object that wraps the file content
and file name into a single object.
* Validates that non-empty file data has been bound to the form.
An ``UploadedFile`` object has two attributes:
====================== =====================================================
Argument Description
====================== =====================================================
``filename`` The name of the file, provided by the uploading
client.
``content`` The array of bytes comprising the file content.
====================== =====================================================
The string representation of an ``UploadedFile`` is the same as the filename
attribute.
When you use a ``FileField`` on a form, you must also remember to
`bind the file data to the form`_.
.. _`bind the file data to the form`: `Binding uploaded files to a form`_
``ImageField``
~~~~~~~~~~~~~~
**New in Django development version**
* Default widget: ``FileInput``
* Empty value: ``None``
* Normalizes to: An ``UploadedFile`` object that wraps the file content
and file name into a single object.
* Validates that file data has been bound to the form, and that the
file is of an image format understood by PIL.
Using an ImageField requires that the `Python Imaging Library`_ is installed.
When you use a ``FileField`` on a form, you must also remember to
`bind the file data to the form`_.
.. _Python Imaging Library: http://www.pythonware.com/products/pil/
``IntegerField`` ``IntegerField``
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
@ -1222,7 +1313,7 @@ Custom form and field validation
Form validation happens when the data is cleaned. If you want to customise Form validation happens when the data is cleaned. If you want to customise
this process, there are various places you can change, each one serving a this process, there are various places you can change, each one serving a
different purpose. Thee types of cleaning methods are run during form different purpose. Three types of cleaning methods are run during form
processing. These are normally executed when you call the ``is_valid()`` processing. These are normally executed when you call the ``is_valid()``
method on a form. There are other things that can trigger cleaning and method on a form. There are other things that can trigger cleaning and
validation (accessing the ``errors`` attribute or calling ``full_clean()`` validation (accessing the ``errors`` attribute or calling ``full_clean()``
@ -1372,17 +1463,17 @@ the full list of conversions:
``AutoField`` Not represented in the form ``AutoField`` Not represented in the form
``BooleanField`` ``BooleanField`` ``BooleanField`` ``BooleanField``
``CharField`` ``CharField`` with ``max_length`` set to ``CharField`` ``CharField`` with ``max_length`` set to
the model field's ``maxlength`` the model field's ``max_length``
``CommaSeparatedIntegerField`` ``CharField`` ``CommaSeparatedIntegerField`` ``CharField``
``DateField`` ``DateField`` ``DateField`` ``DateField``
``DateTimeField`` ``DateTimeField`` ``DateTimeField`` ``DateTimeField``
``DecimalField`` ``DecimalField`` ``DecimalField`` ``DecimalField``
``EmailField`` ``EmailField`` ``EmailField`` ``EmailField``
``FileField`` ``CharField`` ``FileField`` ``FileField``
``FilePathField`` ``CharField`` ``FilePathField`` ``CharField``
``FloatField`` ``FloatField`` ``FloatField`` ``FloatField``
``ForeignKey`` ``ModelChoiceField`` (see below) ``ForeignKey`` ``ModelChoiceField`` (see below)
``ImageField`` ``CharField`` ``ImageField`` ``ImageField``
``IntegerField`` ``IntegerField`` ``IntegerField`` ``IntegerField``
``IPAddressField`` ``CharField`` ``IPAddressField`` ``CharField``
``ManyToManyField`` ``ModelMultipleChoiceField`` (see ``ManyToManyField`` ``ModelMultipleChoiceField`` (see
@ -1452,15 +1543,15 @@ Consider this set of models::
) )
class Author(models.Model): class Author(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
title = models.CharField(maxlength=3, choices=TITLE_CHOICES) title = models.CharField(max_length=3, choices=TITLE_CHOICES)
birth_date = models.DateField(blank=True, null=True) birth_date = models.DateField(blank=True, null=True)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Book(models.Model): class Book(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
authors = models.ManyToManyField(Author) authors = models.ManyToManyField(Author)
With these models, a call to ``form_for_model(Author)`` would return a ``Form`` With these models, a call to ``form_for_model(Author)`` would return a ``Form``
@ -1502,6 +1593,44 @@ the database. In this case, it's up to you to call ``save()`` on the resulting
model instance. This is useful if you want to do custom processing on the model instance. This is useful if you want to do custom processing on the
object before saving it. ``commit`` is ``True`` by default. object before saving it. ``commit`` is ``True`` by default.
Another side effect of using ``commit=False`` is seen when your model has
a many-to-many relation with another model. If your model has a many-to-many
relation and you specify ``commit=False`` when you save a form, Django cannot
immediately save the form data for the many-to-many relation. This is because
it isn't possible to save many-to-many data for an instance until the instance
exists in the database.
To work around this problem, every time you save a form using ``commit=False``,
Django adds a ``save_m2m()`` method to the form created by ``form_for_model``.
After you've manually saved the instance produced by the form, you can invoke
``save_m2m()`` to save the many-to-many form data. For example::
# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)
# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)
# Modify the author in some way.
>>> new_author.some_field = 'some_value'
# Save the new instance.
>>> new_author.save()
# Now, save the many-to-many data for the form.
>>> f.save_m2m()
Calling ``save_m2m()`` is only required if you use ``save(commit=False)``.
When you use a simple ``save()`` on a form, all data -- including
many-to-many data -- is saved without the need for any additional method calls.
For example::
# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)
# Create and save the new author instance. There's no need to do anything else.
>>> new_author = f.save()
Using an alternate base class Using an alternate base class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -25,14 +25,14 @@ far, it's been solving two years' worth of database-schema problems. Here's a
quick example:: quick example::
class Reporter(models.Model): class Reporter(models.Model):
full_name = models.CharField(maxlength=70) full_name = models.CharField(max_length=70)
def __unicode__(self): def __unicode__(self):
return self.full_name return self.full_name
class Article(models.Model): class Article(models.Model):
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
headline = models.CharField(maxlength=200) headline = models.CharField(max_length=200)
article = models.TextField() article = models.TextField()
reporter = models.ForeignKey(Reporter) reporter = models.ForeignKey(Reporter)
@ -134,7 +134,7 @@ your model classes::
class Article(models.Model): class Article(models.Model):
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
headline = models.CharField(maxlength=200) headline = models.CharField(max_length=200)
article = models.TextField() article = models.TextField()
reporter = models.ForeignKey(Reporter) reporter = models.ForeignKey(Reporter)
class Admin: pass class Admin: pass
@ -288,14 +288,16 @@ This has been only a quick overview of Django's functionality. Some more useful
features: features:
* A caching framework that integrates with memcached or other backends. * A caching framework that integrates with memcached or other backends.
* A syndication framework that makes creating RSS and Atom feeds as easy as * A `syndication framework`_ that makes creating RSS and Atom feeds as easy as
writing a small Python class. writing a small Python class.
* More sexy automatically-generated admin features -- this overview barely * More sexy automatically-generated admin features -- this overview barely
scratched the surface. scratched the surface.
.. _syndication framework: ../syndication_feeds/
The next obvious steps are for you to `download Django`_, read `the tutorial`_ The next obvious steps are for you to `download Django`_, read `the tutorial`_
and join `the community`_. Thanks for your interest! and join `the community`_. Thanks for your interest!
.. _download Django: http://www.djangoproject.com/download/ .. _download Django: http://www.djangoproject.com/download/
.. _the tutorial: http://www.djangoproject.com/documentation/tutorial01/ .. _the tutorial: ../tutorial01/
.. _the community: http://www.djangoproject.com/community/ .. _the community: http://www.djangoproject.com/community/

View File

@ -114,7 +114,7 @@ there's a #django channel on irc.freenode.net that is regularly populated by
Django users and developers from around the world. Friendly people are usually Django users and developers from around the world. Friendly people are usually
available at any hour of the day -- to help, or just to chat. available at any hour of the day -- to help, or just to chat.
.. _online: http://www.djangoproject.com/documentation/ .. _online: http://www.djangoproject.com/documentation/0.95/
.. _Django website: http://www.djangoproject.com/ .. _Django website: http://www.djangoproject.com/
.. _FAQ: http://www.djangoproject.com/documentation/faq/ .. _FAQ: http://www.djangoproject.com/documentation/faq/
.. _django-users: http://groups.google.com/group/django-users .. _django-users: http://groups.google.com/group/django-users

View File

@ -297,7 +297,7 @@ In contrast to ``HttpRequest`` objects, which are created automatically by
Django, ``HttpResponse`` objects are your responsibility. Each view you write Django, ``HttpResponse`` objects are your responsibility. Each view you write
is responsible for instantiating, populating and returning an ``HttpResponse``. is responsible for instantiating, populating and returning an ``HttpResponse``.
The ``HttpResponse`` class lives at ``django.http.HttpResponse``. The ``HttpResponse`` class lives in the ``django.http`` module.
Usage Usage
----- -----

View File

@ -21,7 +21,7 @@ you express this information in Python code.
It works much like Django's `syndication framework`_. To create a sitemap, just It works much like Django's `syndication framework`_. To create a sitemap, just
write a ``Sitemap`` class and point to it in your URLconf_. write a ``Sitemap`` class and point to it in your URLconf_.
.. _syndication framework: ../syndication/ .. _syndication framework: ../syndication_feeds/
.. _URLconf: ../url_dispatch/ .. _URLconf: ../url_dispatch/
Installation Installation

View File

@ -46,7 +46,7 @@ that's represented by a ``ManyToManyField`` in the ``Article`` model::
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=200) headline = models.CharField(max_length=200)
# ... # ...
sites = models.ManyToManyField(Site) sites = models.ManyToManyField(Site)
@ -87,7 +87,7 @@ like this::
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=200) headline = models.CharField(max_length=200)
# ... # ...
site = models.ForeignKey(Site) site = models.ForeignKey(Site)
@ -229,7 +229,7 @@ Use ``CurrentSiteManager`` by adding it to your model explicitly. For example::
class Photo(models.Model): class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos') photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(maxlength=100) photographer_name = models.CharField(max_length=100)
pub_date = models.DateField() pub_date = models.DateField()
site = models.ForeignKey(Site) site = models.ForeignKey(Site)
objects = models.Manager() objects = models.Manager()
@ -257,7 +257,7 @@ this::
class Photo(models.Model): class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos') photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(maxlength=100) photographer_name = models.CharField(max_length=100)
pub_date = models.DateField() pub_date = models.DateField()
publish_on = models.ForeignKey(Site) publish_on = models.ForeignKey(Site)
objects = models.Manager() objects = models.Manager()
@ -318,7 +318,7 @@ Here's how Django uses the sites framework:
.. _redirects framework: ../redirects/ .. _redirects framework: ../redirects/
.. _flatpages framework: ../flatpages/ .. _flatpages framework: ../flatpages/
.. _syndication framework: ../syndication/ .. _syndication framework: ../syndication_feeds/
.. _authentication framework: ../authentication/ .. _authentication framework: ../authentication/
``RequestSite`` objects ``RequestSite`` objects

View File

@ -79,8 +79,8 @@ For example::
'The cat says "meow"' 'The cat says "meow"'
""" """
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
sound = models.CharField(maxlength=20) sound = models.CharField(max_length=20)
def speak(self): def speak(self):
return 'The %s says "%s"' % (self.name, self.sound) return 'The %s says "%s"' % (self.name, self.sound)

View File

@ -251,12 +251,12 @@ These concepts are represented by simple Python classes. Edit the
from django.db import models from django.db import models
class Poll(models.Model): class Poll(models.Model):
question = models.CharField(maxlength=200) question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published') pub_date = models.DateTimeField('date published')
class Choice(models.Model): class Choice(models.Model):
poll = models.ForeignKey(Poll) poll = models.ForeignKey(Poll)
choice = models.CharField(maxlength=200) choice = models.CharField(max_length=200)
votes = models.IntegerField() votes = models.IntegerField()
The code is straightforward. Each model is represented by a class that The code is straightforward. Each model is represented by a class that
@ -279,7 +279,7 @@ name for ``Poll.pub_date``. For all other fields in this model, the field's
machine-readable name will suffice as its human-readable name. machine-readable name will suffice as its human-readable name.
Some ``Field`` classes have required elements. ``CharField``, for example, Some ``Field`` classes have required elements. ``CharField``, for example,
requires that you give it a ``maxlength``. That's used not only in the database requires that you give it a ``max_length``. That's used not only in the database
schema, but in validation, as we'll soon see. schema, but in validation, as we'll soon see.
Finally, note a relationship is defined, using ``models.ForeignKey``. That tells Finally, note a relationship is defined, using ``models.ForeignKey``. That tells

View File

@ -240,7 +240,7 @@ default, provide enough fields for 3 Choices."
Then change the other fields in ``Choice`` to give them ``core=True``:: Then change the other fields in ``Choice`` to give them ``core=True``::
choice = models.CharField(maxlength=200, core=True) choice = models.CharField(max_length=200, core=True)
votes = models.IntegerField(core=True) votes = models.IntegerField(core=True)
This tells Django: "When you edit a Choice on the Poll admin page, the 'choice' This tells Django: "When you edit a Choice on the Poll admin page, the 'choice'

View File

@ -356,7 +356,8 @@ Use the template system
======================= =======================
Back to the ``detail()`` view for our poll application. Given the context Back to the ``detail()`` view for our poll application. Given the context
variable ``poll``, here's what the template might look like:: variable ``poll``, here's what the "polls/detail.html" template might look
like::
<h1>{{ poll.question }}</h1> <h1>{{ poll.question }}</h1>
<ul> <ul>

View File

@ -8,8 +8,8 @@ application and will focus on simple form processing and cutting down our code.
Write a simple form Write a simple form
=================== ===================
Let's update our poll detail template from the last tutorial, so that the Let's update our poll detail template ("polls/detail.html") from the last
template contains an HTML ``<form>`` element:: tutorial, so that the template contains an HTML ``<form>`` element::
<h1>{{ poll.question }}</h1> <h1>{{ poll.question }}</h1>
@ -213,7 +213,7 @@ objects" and "display a detail page for a particular type of object."
a way to refer to its URL later on (see `naming URL patterns`_ for more on a way to refer to its URL later on (see `naming URL patterns`_ for more on
named patterns). named patterns).
.. _naming URL patterns: http://www.djangoproject.com/documentation/url_dispatch/#naming-url-patterns .. _naming URL patterns: ../url_dispatch/#naming-url-patterns
By default, the ``object_detail`` generic view uses a template called By default, the ``object_detail`` generic view uses a template called
``<app name>/<model name>_detail.html``. In our case, it'll use the template ``<app name>/<model name>_detail.html``. In our case, it'll use the template

View File

@ -404,7 +404,7 @@ This technique is used in `generic views`_ and in the `syndication framework`_
to pass metadata and options to views. to pass metadata and options to views.
.. _generic views: ../generic_views/ .. _generic views: ../generic_views/
.. _syndication framework: ../syndication/ .. _syndication framework: ../syndication_feeds/
.. admonition:: Dealing with conflicts .. admonition:: Dealing with conflicts

View File

@ -8,7 +8,7 @@ This is a basic model with only two non-primary-key fields.
from django.db import models from django.db import models
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100, default='Default headline') headline = models.CharField(max_length=100, default='Default headline')
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
class Meta: class Meta:

View File

@ -17,8 +17,8 @@ GENDER_CHOICES = (
) )
class Person(models.Model): class Person(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES) gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
def __unicode__(self): def __unicode__(self):
return self.name return self.name

View File

@ -18,8 +18,8 @@ ManyToMany field. This has no effect on the API for querying the database.
from django.db import models from django.db import models
class Author(models.Model): class Author(models.Model):
first_name = models.CharField(maxlength=30, db_column='firstname') first_name = models.CharField(max_length=30, db_column='firstname')
last_name = models.CharField(maxlength=30, db_column='last') last_name = models.CharField(max_length=30, db_column='last')
def __unicode__(self): def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name) return u'%s %s' % (self.first_name, self.last_name)
@ -29,7 +29,7 @@ class Author(models.Model):
ordering = ('last_name','first_name') ordering = ('last_name','first_name')
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
authors = models.ManyToManyField(Author, db_table='my_m2m_table') authors = models.ManyToManyField(Author, db_table='my_m2m_table')
def __unicode__(self): def __unicode__(self):

View File

@ -18,8 +18,8 @@ class PersonManager(models.Manager):
return self.filter(fun=True) return self.filter(fun=True)
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(maxlength=30) last_name = models.CharField(max_length=30)
fun = models.BooleanField() fun = models.BooleanField()
objects = PersonManager() objects = PersonManager()
@ -33,8 +33,8 @@ class PublishedBookManager(models.Manager):
return super(PublishedBookManager, self).get_query_set().filter(is_published=True) return super(PublishedBookManager, self).get_query_set().filter(is_published=True)
class Book(models.Model): class Book(models.Model):
title = models.CharField(maxlength=50) title = models.CharField(max_length=50)
author = models.CharField(maxlength=30) author = models.CharField(max_length=30)
is_published = models.BooleanField() is_published = models.BooleanField()
published_objects = PublishedBookManager() published_objects = PublishedBookManager()
authors = models.ManyToManyField(Person, related_name='books') authors = models.ManyToManyField(Person, related_name='books')
@ -49,7 +49,7 @@ class FastCarManager(models.Manager):
return super(FastCarManager, self).get_query_set().filter(top_speed__gt=150) return super(FastCarManager, self).get_query_set().filter(top_speed__gt=150)
class Car(models.Model): class Car(models.Model):
name = models.CharField(maxlength=10) name = models.CharField(max_length=10)
mileage = models.IntegerField() mileage = models.IntegerField()
top_speed = models.IntegerField(help_text="In miles per hour.") top_speed = models.IntegerField(help_text="In miles per hour.")
cars = models.Manager() cars = models.Manager()

View File

@ -8,7 +8,7 @@ from django.db import models
import datetime import datetime
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
pub_date = models.DateField() pub_date = models.DateField()
def __unicode__(self): def __unicode__(self):

View File

@ -8,10 +8,10 @@ this behavior by explicitly adding ``primary_key=True`` to a field.
from django.db import models from django.db import models
class Employee(models.Model): class Employee(models.Model):
employee_code = models.CharField(maxlength=10, primary_key=True, employee_code = models.CharField(max_length=10, primary_key=True,
db_column = 'code') db_column = 'code')
first_name = models.CharField(maxlength=20) first_name = models.CharField(max_length=20)
last_name = models.CharField(maxlength=20) last_name = models.CharField(max_length=20)
class Meta: class Meta:
ordering = ('last_name', 'first_name') ordering = ('last_name', 'first_name')
@ -19,7 +19,7 @@ class Employee(models.Model):
return u"%s %s" % (self.first_name, self.last_name) return u"%s %s" % (self.first_name, self.last_name)
class Business(models.Model): class Business(models.Model):
name = models.CharField(maxlength=20, primary_key=True) name = models.CharField(max_length=20, primary_key=True)
employees = models.ManyToManyField(Employee) employees = models.ManyToManyField(Employee)
class Meta: class Meta:
verbose_name_plural = 'businesses' verbose_name_plural = 'businesses'

View File

@ -13,7 +13,7 @@ from django.db import models
from datetime import datetime from datetime import datetime
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100, default='Default headline') headline = models.CharField(max_length=100, default='Default headline')
pub_date = models.DateTimeField(default=datetime.now) pub_date = models.DateTimeField(default=datetime.now)
def __unicode__(self): def __unicode__(self):

View File

@ -11,7 +11,7 @@ FIXTURE_DIRS setting.
from django.db import models from django.db import models
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100, default='Default headline') headline = models.CharField(max_length=100, default='Default headline')
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
def __unicode__(self): def __unicode__(self):

View File

@ -28,8 +28,8 @@ class TaggedItem(models.Model):
return self.tag return self.tag
class Animal(models.Model): class Animal(models.Model):
common_name = models.CharField(maxlength=150) common_name = models.CharField(max_length=150)
latin_name = models.CharField(maxlength=150) latin_name = models.CharField(max_length=150)
tags = generic.GenericRelation(TaggedItem) tags = generic.GenericRelation(TaggedItem)
@ -37,7 +37,7 @@ class Animal(models.Model):
return self.common_name return self.common_name
class Vegetable(models.Model): class Vegetable(models.Model):
name = models.CharField(maxlength=150) name = models.CharField(max_length=150)
is_yucky = models.BooleanField(default=True) is_yucky = models.BooleanField(default=True)
tags = generic.GenericRelation(TaggedItem) tags = generic.GenericRelation(TaggedItem)
@ -46,7 +46,7 @@ class Vegetable(models.Model):
return self.name return self.name
class Mineral(models.Model): class Mineral(models.Model):
name = models.CharField(maxlength=150) name = models.CharField(max_length=150)
hardness = models.PositiveSmallIntegerField() hardness = models.PositiveSmallIntegerField()
# note the lack of an explicit GenericRelation here... # note the lack of an explicit GenericRelation here...

View File

@ -11,7 +11,7 @@ into the future."
from django.db import models from django.db import models
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
pub_date = models.DateField() pub_date = models.DateField()
expire_date = models.DateField() expire_date = models.DateField()
class Meta: class Meta:
@ -21,7 +21,7 @@ class Article(models.Model):
return self.headline return self.headline
class Person(models.Model): class Person(models.Model):
name = models.CharField(maxlength=30) name = models.CharField(max_length=30)
birthday = models.DateField() birthday = models.DateField()
# Note that this model doesn't have "get_latest_by" set. # Note that this model doesn't have "get_latest_by" set.

View File

@ -15,7 +15,7 @@ from django.http import Http404
from django.shortcuts import get_object_or_404, get_list_or_404 from django.shortcuts import get_object_or_404, get_list_or_404
class Author(models.Model): class Author(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
@ -26,7 +26,7 @@ class ArticleManager(models.Manager):
class Article(models.Model): class Article(models.Model):
authors = models.ManyToManyField(Author) authors = models.ManyToManyField(Author)
title = models.CharField(maxlength=50) title = models.CharField(max_length=50)
objects = models.Manager() objects = models.Manager()
by_a_sir = ArticleManager() by_a_sir = ArticleManager()

View File

@ -8,8 +8,8 @@ parameters. If an object isn't found, it creates one with the given parameters.
from django.db import models from django.db import models
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=100) first_name = models.CharField(max_length=100)
last_name = models.CharField(maxlength=100) last_name = models.CharField(max_length=100)
birthday = models.DateField() birthday = models.DateField()
def __unicode__(self): def __unicode__(self):

View File

@ -10,26 +10,26 @@ class FieldErrors(models.Model):
charfield = models.CharField() charfield = models.CharField()
decimalfield = models.DecimalField() decimalfield = models.DecimalField()
filefield = models.FileField() filefield = models.FileField()
prepopulate = models.CharField(maxlength=10, prepopulate_from='bad') prepopulate = models.CharField(max_length=10, prepopulate_from='bad')
choices = models.CharField(maxlength=10, choices='bad') choices = models.CharField(max_length=10, choices='bad')
choices2 = models.CharField(maxlength=10, choices=[(1,2,3),(1,2,3)]) choices2 = models.CharField(max_length=10, choices=[(1,2,3),(1,2,3)])
index = models.CharField(maxlength=10, db_index='bad') index = models.CharField(max_length=10, db_index='bad')
class Target(models.Model): class Target(models.Model):
tgt_safe = models.CharField(maxlength=10) tgt_safe = models.CharField(max_length=10)
clash1 = models.CharField(maxlength=10) clash1 = models.CharField(max_length=10)
clash2 = models.CharField(maxlength=10) clash2 = models.CharField(max_length=10)
clash1_set = models.CharField(maxlength=10) clash1_set = models.CharField(max_length=10)
class Clash1(models.Model): class Clash1(models.Model):
src_safe = models.CharField(maxlength=10, core=True) src_safe = models.CharField(max_length=10, core=True)
foreign = models.ForeignKey(Target) foreign = models.ForeignKey(Target)
m2m = models.ManyToManyField(Target) m2m = models.ManyToManyField(Target)
class Clash2(models.Model): class Clash2(models.Model):
src_safe = models.CharField(maxlength=10, core=True) src_safe = models.CharField(max_length=10, core=True)
foreign_1 = models.ForeignKey(Target, related_name='id') foreign_1 = models.ForeignKey(Target, related_name='id')
foreign_2 = models.ForeignKey(Target, related_name='src_safe') foreign_2 = models.ForeignKey(Target, related_name='src_safe')
@ -38,7 +38,7 @@ class Clash2(models.Model):
m2m_2 = models.ManyToManyField(Target, related_name='src_safe') m2m_2 = models.ManyToManyField(Target, related_name='src_safe')
class Target2(models.Model): class Target2(models.Model):
clash3 = models.CharField(maxlength=10) clash3 = models.CharField(max_length=10)
foreign_tgt = models.ForeignKey(Target) foreign_tgt = models.ForeignKey(Target)
clashforeign_set = models.ForeignKey(Target) clashforeign_set = models.ForeignKey(Target)
@ -46,7 +46,7 @@ class Target2(models.Model):
clashm2m_set = models.ManyToManyField(Target) clashm2m_set = models.ManyToManyField(Target)
class Clash3(models.Model): class Clash3(models.Model):
src_safe = models.CharField(maxlength=10, core=True) src_safe = models.CharField(max_length=10, core=True)
foreign_1 = models.ForeignKey(Target2, related_name='foreign_tgt') foreign_1 = models.ForeignKey(Target2, related_name='foreign_tgt')
foreign_2 = models.ForeignKey(Target2, related_name='m2m_tgt') foreign_2 = models.ForeignKey(Target2, related_name='m2m_tgt')
@ -61,16 +61,16 @@ class ClashM2M(models.Model):
m2m = models.ManyToManyField(Target2) m2m = models.ManyToManyField(Target2)
class SelfClashForeign(models.Model): class SelfClashForeign(models.Model):
src_safe = models.CharField(maxlength=10, core=True) src_safe = models.CharField(max_length=10, core=True)
selfclashforeign = models.CharField(maxlength=10) selfclashforeign = models.CharField(max_length=10)
selfclashforeign_set = models.ForeignKey("SelfClashForeign") selfclashforeign_set = models.ForeignKey("SelfClashForeign")
foreign_1 = models.ForeignKey("SelfClashForeign", related_name='id') foreign_1 = models.ForeignKey("SelfClashForeign", related_name='id')
foreign_2 = models.ForeignKey("SelfClashForeign", related_name='src_safe') foreign_2 = models.ForeignKey("SelfClashForeign", related_name='src_safe')
class ValidM2M(models.Model): class ValidM2M(models.Model):
src_safe = models.CharField(maxlength=10) src_safe = models.CharField(max_length=10)
validm2m = models.CharField(maxlength=10) validm2m = models.CharField(max_length=10)
# M2M fields are symmetrical by default. Symmetrical M2M fields # M2M fields are symmetrical by default. Symmetrical M2M fields
# on self don't require a related accessor, so many potential # on self don't require a related accessor, so many potential
@ -84,8 +84,8 @@ class ValidM2M(models.Model):
m2m_4 = models.ManyToManyField('self') m2m_4 = models.ManyToManyField('self')
class SelfClashM2M(models.Model): class SelfClashM2M(models.Model):
src_safe = models.CharField(maxlength=10) src_safe = models.CharField(max_length=10)
selfclashm2m = models.CharField(maxlength=10) selfclashm2m = models.CharField(max_length=10)
# Non-symmetrical M2M fields _do_ have related accessors, so # Non-symmetrical M2M fields _do_ have related accessors, so
# there is potential for clashes. # there is potential for clashes.
@ -100,14 +100,14 @@ class SelfClashM2M(models.Model):
class Model(models.Model): class Model(models.Model):
"But it's valid to call a model Model." "But it's valid to call a model Model."
year = models.PositiveIntegerField() #1960 year = models.PositiveIntegerField() #1960
make = models.CharField(maxlength=10) #Aston Martin make = models.CharField(max_length=10) #Aston Martin
name = models.CharField(maxlength=10) #DB 4 GT name = models.CharField(max_length=10) #DB 4 GT
class Car(models.Model): class Car(models.Model):
colour = models.CharField(maxlength=5) colour = models.CharField(max_length=5)
model = models.ForeignKey(Model) model = models.ForeignKey(Model)
model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "maxlength" attribute. model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute.
invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute. invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute.
invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute. invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute.
invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute. invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute.

View File

@ -8,7 +8,7 @@ from django.db import models
from django.conf import settings from django.conf import settings
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
class Meta: class Meta:
ordering = ('-pub_date', 'headline') ordering = ('-pub_date', 'headline')

View File

@ -7,7 +7,7 @@ Make sure to set ``related_name`` if you use relationships to the same table.
from django.db import models from django.db import models
class User(models.Model): class User(models.Model):
username = models.CharField(maxlength=20) username = models.CharField(max_length=20)
class Issue(models.Model): class Issue(models.Model):
num = models.IntegerField() num = models.IntegerField()

View File

@ -13,14 +13,14 @@ writer").
from django.db import models from django.db import models
class Reporter(models.Model): class Reporter(models.Model):
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(maxlength=30) last_name = models.CharField(max_length=30)
def __unicode__(self): def __unicode__(self):
return u"%s %s" % (self.first_name, self.last_name) return u"%s %s" % (self.first_name, self.last_name)
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
pub_date = models.DateField() pub_date = models.DateField()
def __unicode__(self): def __unicode__(self):
@ -29,7 +29,7 @@ class Article(models.Model):
class Writer(models.Model): class Writer(models.Model):
reporter = models.ForeignKey(Reporter) reporter = models.ForeignKey(Reporter)
article = models.ForeignKey(Article) article = models.ForeignKey(Article)
position = models.CharField(maxlength=100) position = models.CharField(max_length=100)
def __unicode__(self): def __unicode__(self):
return u'%s (%s)' % (self.reporter, self.position) return u'%s (%s)' % (self.reporter, self.position)

View File

@ -10,7 +10,7 @@ Set ``related_name`` to designate what the reverse relationship is called.
from django.db import models from django.db import models
class Category(models.Model): class Category(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
class Meta: class Meta:
ordering = ('name',) ordering = ('name',)
@ -18,7 +18,7 @@ class Category(models.Model):
return self.name return self.name
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=50) headline = models.CharField(max_length=50)
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
primary_categories = models.ManyToManyField(Category, related_name='primary_article_set') primary_categories = models.ManyToManyField(Category, related_name='primary_article_set')
secondary_categories = models.ManyToManyField(Category, related_name='secondary_article_set') secondary_categories = models.ManyToManyField(Category, related_name='secondary_article_set')

View File

@ -15,7 +15,7 @@ there will be a clash, and tests that symmetry is preserved where appropriate.
from django.db import models from django.db import models
class Person(models.Model): class Person(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
friends = models.ManyToManyField('self') friends = models.ManyToManyField('self')
idols = models.ManyToManyField('self', symmetrical=False, related_name='stalkers') idols = models.ManyToManyField('self', symmetrical=False, related_name='stalkers')

View File

@ -13,7 +13,7 @@ Set ``related_name`` to designate what the reverse relationship is called.
from django.db import models from django.db import models
class Category(models.Model): class Category(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
parent = models.ForeignKey('self', null=True, related_name='child_set') parent = models.ForeignKey('self', null=True, related_name='child_set')
def __unicode__(self): def __unicode__(self):

View File

@ -10,7 +10,7 @@ Set ``related_name`` to designate what the reverse relationship is called.
from django.db import models from django.db import models
class Person(models.Model): class Person(models.Model):
full_name = models.CharField(maxlength=20) full_name = models.CharField(max_length=20)
mother = models.ForeignKey('self', null=True, related_name='mothers_child_set') mother = models.ForeignKey('self', null=True, related_name='mothers_child_set')
father = models.ForeignKey('self', null=True, related_name='fathers_child_set') father = models.ForeignKey('self', null=True, related_name='fathers_child_set')

View File

@ -7,14 +7,14 @@ Each model gets an AddManipulator and ChangeManipulator by default.
from django.db import models from django.db import models
class Musician(models.Model): class Musician(models.Model):
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(maxlength=30) last_name = models.CharField(max_length=30)
def __unicode__(self): def __unicode__(self):
return u"%s %s" % (self.first_name, self.last_name) return u"%s %s" % (self.first_name, self.last_name)
class Album(models.Model): class Album(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
musician = models.ForeignKey(Musician) musician = models.ForeignKey(Musician)
release_date = models.DateField(blank=True, null=True) release_date = models.DateField(blank=True, null=True)

View File

@ -10,7 +10,7 @@ and a publication has multiple articles.
from django.db import models from django.db import models
class Publication(models.Model): class Publication(models.Model):
title = models.CharField(maxlength=30) title = models.CharField(max_length=30)
def __unicode__(self): def __unicode__(self):
return self.title return self.title
@ -19,7 +19,7 @@ class Publication(models.Model):
ordering = ('title',) ordering = ('title',)
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
publications = models.ManyToManyField(Publication) publications = models.ManyToManyField(Publication)
def __unicode__(self): def __unicode__(self):

View File

@ -7,15 +7,15 @@ To define a many-to-one relationship, use ``ForeignKey()`` .
from django.db import models from django.db import models
class Reporter(models.Model): class Reporter(models.Model):
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(maxlength=30) last_name = models.CharField(max_length=30)
email = models.EmailField() email = models.EmailField()
def __unicode__(self): def __unicode__(self):
return u"%s %s" % (self.first_name, self.last_name) return u"%s %s" % (self.first_name, self.last_name)
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
pub_date = models.DateField() pub_date = models.DateField()
reporter = models.ForeignKey(Reporter) reporter = models.ForeignKey(Reporter)

View File

@ -8,13 +8,13 @@ To define a many-to-one relationship that can have a null foreign key, use
from django.db import models from django.db import models
class Reporter(models.Model): class Reporter(models.Model):
name = models.CharField(maxlength=30) name = models.CharField(max_length=30)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
reporter = models.ForeignKey(Reporter, null=True) reporter = models.ForeignKey(Reporter, null=True)
class Meta: class Meta:

View File

@ -31,20 +31,20 @@ ARTICLE_STATUS = (
) )
class Category(models.Model): class Category(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
url = models.CharField('The URL', maxlength=40) url = models.CharField('The URL', max_length=40)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Writer(models.Model): class Writer(models.Model):
name = models.CharField(maxlength=50, help_text='Use both first and last names.') name = models.CharField(max_length=50, help_text='Use both first and last names.')
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=50) headline = models.CharField(max_length=50)
pub_date = models.DateField() pub_date = models.DateField()
created = models.DateField(editable=False) created = models.DateField(editable=False)
writer = models.ForeignKey(Writer) writer = models.ForeignKey(Writer)
@ -63,7 +63,7 @@ class Article(models.Model):
class PhoneNumber(models.Model): class PhoneNumber(models.Model):
phone = models.PhoneNumberField() phone = models.PhoneNumberField()
description = models.CharField(maxlength=20) description = models.CharField(max_length=20)
def __unicode__(self): def __unicode__(self):
return self.phone return self.phone
@ -332,6 +332,28 @@ Create a new article, with no categories, via the form.
>>> new_art.categories.all() >>> new_art.categories.all()
[] []
Create a new article, with categories, via the form, but use commit=False.
The m2m data won't be saved until save_m2m() is invoked on the form.
>>> ArticleForm = form_for_model(Article)
>>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01',
... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
>>> new_art = f.save(commit=False)
# Manually save the instance
>>> new_art.save()
>>> new_art.id
4
# The instance doesn't have m2m data yet
>>> new_art = Article.objects.get(id=4)
>>> new_art.categories.all()
[]
# Save the m2m data on the form
>>> f.save_m2m()
>>> new_art.categories.all()
[<Category: Entertainment>, <Category: It's a test>]
Here, we define a custom Form. Because it happens to have the same fields as Here, we define a custom Form. Because it happens to have the same fields as
the Category model, we can use save_instance() to apply its changes to an the Category model, we can use save_instance() to apply its changes to an
existing Category instance. existing Category instance.

View File

@ -7,8 +7,8 @@ Model inheritance isn't yet supported.
from django.db import models from django.db import models
class Place(models.Model): class Place(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
address = models.CharField(maxlength=80) address = models.CharField(max_length=80)
def __unicode__(self): def __unicode__(self):
return u"%s the place" % self.name return u"%s the place" % self.name

View File

@ -7,11 +7,11 @@ To define a many-to-one relationship, use ``ForeignKey()`` .
from django.db.models import * from django.db.models import *
class Parent(Model): class Parent(Model):
name = CharField(maxlength=100, core=True) name = CharField(max_length=100, core=True)
bestchild = ForeignKey("Child", null=True, related_name="favoured_by") bestchild = ForeignKey("Child", null=True, related_name="favoured_by")
class Child(Model): class Child(Model):
name = CharField(maxlength=100) name = CharField(max_length=100)
parent = ForeignKey(Parent) parent = ForeignKey(Parent)
__test__ = {'API_TESTS':""" __test__ = {'API_TESTS':"""

View File

@ -9,8 +9,8 @@ In this example, a ``Place`` optionally can be a ``Restaurant``.
from django.db import models from django.db import models
class Place(models.Model): class Place(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
address = models.CharField(maxlength=80) address = models.CharField(max_length=80)
def __unicode__(self): def __unicode__(self):
return u"%s the place" % self.name return u"%s the place" % self.name
@ -25,18 +25,18 @@ class Restaurant(models.Model):
class Waiter(models.Model): class Waiter(models.Model):
restaurant = models.ForeignKey(Restaurant) restaurant = models.ForeignKey(Restaurant)
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
def __unicode__(self): def __unicode__(self):
return u"%s the waiter at %s" % (self.name, self.restaurant) return u"%s the waiter at %s" % (self.name, self.restaurant)
class ManualPrimaryKey(models.Model): class ManualPrimaryKey(models.Model):
primary_key = models.CharField(maxlength=10, primary_key=True) primary_key = models.CharField(max_length=10, primary_key=True)
name = models.CharField(maxlength = 50) name = models.CharField(max_length = 50)
class RelatedModel(models.Model): class RelatedModel(models.Model):
link = models.OneToOneField(ManualPrimaryKey) link = models.OneToOneField(ManualPrimaryKey)
name = models.CharField(maxlength = 50) name = models.CharField(max_length = 50)
__test__ = {'API_TESTS':""" __test__ = {'API_TESTS':"""
# Create a couple of Places. # Create a couple of Places.

View File

@ -14,7 +14,7 @@ a get_sql method).
from django.db import models from django.db import models
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=50) headline = models.CharField(max_length=50)
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
class Meta: class Meta:

View File

@ -16,7 +16,7 @@ undefined -- not random, just undefined.
from django.db import models from django.db import models
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
class Meta: class Meta:
ordering = ('-pub_date', 'headline') ordering = ('-pub_date', 'headline')

View File

@ -9,7 +9,7 @@ objects into easily readable pages.
from django.db import models from django.db import models
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100, default='Default headline') headline = models.CharField(max_length=100, default='Default headline')
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
def __unicode__(self): def __unicode__(self):

View File

@ -7,8 +7,8 @@ Use properties on models just like on any other Python object.
from django.db import models from django.db import models
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(maxlength=30) last_name = models.CharField(max_length=30)
def _get_full_name(self): def _get_full_name(self):
return "%s %s" % (self.first_name, self.last_name) return "%s %s" % (self.first_name, self.last_name)

View File

@ -10,14 +10,14 @@ reserved-name usage.
from django.db import models from django.db import models
class Thing(models.Model): class Thing(models.Model):
when = models.CharField(maxlength=1, primary_key=True) when = models.CharField(max_length=1, primary_key=True)
join = models.CharField(maxlength=1) join = models.CharField(max_length=1)
like = models.CharField(maxlength=1) like = models.CharField(max_length=1)
drop = models.CharField(maxlength=1) drop = models.CharField(max_length=1)
alter = models.CharField(maxlength=1) alter = models.CharField(max_length=1)
having = models.CharField(maxlength=1) having = models.CharField(max_length=1)
where = models.DateField(maxlength=1) where = models.DateField(max_length=1)
has_hyphen = models.CharField(maxlength=1, db_column='has-hyphen') has_hyphen = models.CharField(max_length=1, db_column='has-hyphen')
class Meta: class Meta:
db_table = 'select' db_table = 'select'

View File

@ -7,20 +7,20 @@ This demonstrates the reverse lookup features of the database API.
from django.db import models from django.db import models
class User(models.Model): class User(models.Model):
name = models.CharField(maxlength=200) name = models.CharField(max_length=200)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Poll(models.Model): class Poll(models.Model):
question = models.CharField(maxlength=200) question = models.CharField(max_length=200)
creator = models.ForeignKey(User) creator = models.ForeignKey(User)
def __unicode__(self): def __unicode__(self):
return self.question return self.question
class Choice(models.Model): class Choice(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
poll = models.ForeignKey(Poll, related_name="poll_choice") poll = models.ForeignKey(Poll, related_name="poll_choice")
related_poll = models.ForeignKey(Poll, related_name="related_choice") related_poll = models.ForeignKey(Poll, related_name="related_choice")

View File

@ -8,8 +8,8 @@ the methods.
from django.db import models from django.db import models
class Person(models.Model): class Person(models.Model):
first_name = models.CharField(maxlength=20) first_name = models.CharField(max_length=20)
last_name = models.CharField(maxlength=20) last_name = models.CharField(max_length=20)
def __unicode__(self): def __unicode__(self):
return u"%s %s" % (self.first_name, self.last_name) return u"%s %s" % (self.first_name, self.last_name)

View File

@ -12,48 +12,48 @@ from django.db import models
# Who remembers high school biology? # Who remembers high school biology?
class Domain(models.Model): class Domain(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Kingdom(models.Model): class Kingdom(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
domain = models.ForeignKey(Domain) domain = models.ForeignKey(Domain)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Phylum(models.Model): class Phylum(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
kingdom = models.ForeignKey(Kingdom) kingdom = models.ForeignKey(Kingdom)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Klass(models.Model): class Klass(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
phylum = models.ForeignKey(Phylum) phylum = models.ForeignKey(Phylum)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Order(models.Model): class Order(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
klass = models.ForeignKey(Klass) klass = models.ForeignKey(Klass)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Family(models.Model): class Family(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
order = models.ForeignKey(Order) order = models.ForeignKey(Order)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Genus(models.Model): class Genus(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
family = models.ForeignKey(Family) family = models.ForeignKey(Family)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Species(models.Model): class Species(models.Model):
name = models.CharField(maxlength=50) name = models.CharField(max_length=50)
genus = models.ForeignKey(Genus) genus = models.ForeignKey(Genus)
def __unicode__(self): def __unicode__(self):
return self.name return self.name

View File

@ -8,7 +8,7 @@ to and from "flat" data (i.e. strings).
from django.db import models from django.db import models
class Category(models.Model): class Category(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
class Meta: class Meta:
ordering = ('name',) ordering = ('name',)
@ -17,7 +17,7 @@ class Category(models.Model):
return self.name return self.name
class Author(models.Model): class Author(models.Model):
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
class Meta: class Meta:
ordering = ('name',) ordering = ('name',)
@ -27,7 +27,7 @@ class Author(models.Model):
class Article(models.Model): class Article(models.Model):
author = models.ForeignKey(Author) author = models.ForeignKey(Author)
headline = models.CharField(maxlength=50) headline = models.CharField(max_length=50)
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
categories = models.ManyToManyField(Category) categories = models.ManyToManyField(Category)

View File

@ -17,7 +17,7 @@ if you prefer. You must be careful to encode the results correctly, though.
from django.db import models from django.db import models
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
def __str__(self): def __str__(self):
@ -26,7 +26,7 @@ class Article(models.Model):
return self.headline return self.headline
class InternationalArticle(models.Model): class InternationalArticle(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(max_length=100)
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
def __unicode__(self): def __unicode__(self):

View File

@ -10,8 +10,8 @@ manually.
from django.db import models from django.db import models
class Reporter(models.Model): class Reporter(models.Model):
first_name = models.CharField(maxlength=30) first_name = models.CharField(max_length=30)
last_name = models.CharField(maxlength=30) last_name = models.CharField(max_length=30)
email = models.EmailField() email = models.EmailField()
def __unicode__(self): def __unicode__(self):

View File

@ -12,7 +12,7 @@ from django.db import models
class Person(models.Model): class Person(models.Model):
is_child = models.BooleanField() is_child = models.BooleanField()
name = models.CharField(maxlength=20) name = models.CharField(max_length=20)
birthdate = models.DateField() birthdate = models.DateField()
favorite_moment = models.DateTimeField() favorite_moment = models.DateTimeField()
email = models.EmailField() email = models.EmailField()

View File

@ -2,7 +2,7 @@ import tempfile
from django.db import models from django.db import models
class Photo(models.Model): class Photo(models.Model):
title = models.CharField(maxlength=30) title = models.CharField(max_length=30)
image = models.FileField(upload_to=tempfile.gettempdir()) image = models.FileField(upload_to=tempfile.gettempdir())
# Support code for the tests; this keeps track of how many times save() gets # Support code for the tests; this keeps track of how many times save() gets

View File

@ -7,7 +7,7 @@ from django.db import models
from django.conf import settings from django.conf import settings
class Donut(models.Model): class Donut(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(max_length=100)
is_frosted = models.BooleanField(default=False) is_frosted = models.BooleanField(default=False)
has_sprinkles = models.NullBooleanField() has_sprinkles = models.NullBooleanField()
baked_date = models.DateField(null=True) baked_date = models.DateField(null=True)

View File

@ -2,21 +2,21 @@ from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
class Animal(models.Model): class Animal(models.Model):
name = models.CharField(maxlength=150) name = models.CharField(max_length=150)
latin_name = models.CharField(maxlength=150) latin_name = models.CharField(max_length=150)
def __unicode__(self): def __unicode__(self):
return self.common_name return self.common_name
class Plant(models.Model): class Plant(models.Model):
name = models.CharField(maxlength=150) name = models.CharField(max_length=150)
class Meta: class Meta:
# For testing when upper case letter in app name; regression for #4057 # For testing when upper case letter in app name; regression for #4057
db_table = "Fixtures_regress_plant" db_table = "Fixtures_regress_plant"
class Stuff(models.Model): class Stuff(models.Model):
name = models.CharField(maxlength=20, null=True) name = models.CharField(max_length=20, null=True)
owner = models.ForeignKey(User, null=True) owner = models.ForeignKey(User, null=True)
def __unicode__(self): def __unicode__(self):

View File

@ -173,27 +173,29 @@ u'<input type="hidden" class="special" value="foo@example.com" name="email" />'
# FileInput Widget ############################################################ # FileInput Widget ############################################################
FileInput widgets don't ever show the value, because the old value is of no use
if you are updating the form or if the provided file generated an error.
>>> w = FileInput() >>> w = FileInput()
>>> w.render('email', '') >>> w.render('email', '')
u'<input type="file" name="email" />' u'<input type="file" name="email" />'
>>> w.render('email', None) >>> w.render('email', None)
u'<input type="file" name="email" />' u'<input type="file" name="email" />'
>>> w.render('email', 'test@example.com') >>> w.render('email', 'test@example.com')
u'<input type="file" name="email" value="test@example.com" />' u'<input type="file" name="email" />'
>>> w.render('email', 'some "quoted" & ampersanded value') >>> w.render('email', 'some "quoted" & ampersanded value')
u'<input type="file" name="email" value="some &quot;quoted&quot; &amp; ampersanded value" />' u'<input type="file" name="email" />'
>>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) >>> w.render('email', 'test@example.com', attrs={'class': 'fun'})
u'<input type="file" name="email" value="test@example.com" class="fun" />' u'<input type="file" name="email" class="fun" />'
You can also pass 'attrs' to the constructor: You can also pass 'attrs' to the constructor:
>>> w = FileInput(attrs={'class': 'fun'}) >>> w = FileInput(attrs={'class': 'fun'})
>>> w.render('email', '') >>> w.render('email', '')
u'<input type="file" class="fun" name="email" />' u'<input type="file" class="fun" name="email" />'
>>> w.render('email', 'foo@example.com') >>> w.render('email', 'foo@example.com')
u'<input type="file" class="fun" value="foo@example.com" name="email" />' u'<input type="file" class="fun" name="email" />'
>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
u'<input type="file" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' u'<input type="file" class="fun" name="email" />'
# Textarea Widget ############################################################# # Textarea Widget #############################################################
@ -1532,6 +1534,42 @@ Traceback (most recent call last):
... ...
ValidationError: [u'Ensure this value has at most 15 characters (it has 20).'] ValidationError: [u'Ensure this value has at most 15 characters (it has 20).']
# FileField ##################################################################
>>> f = FileField()
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean({})
Traceback (most recent call last):
...
ValidationError: [u'No file was submitted.']
>>> f.clean('some content that is not a file')
Traceback (most recent call last):
...
ValidationError: [u'No file was submitted. Check the encoding type on the form.']
>>> f.clean({'filename': 'name', 'content':None})
Traceback (most recent call last):
...
ValidationError: [u'The submitted file is empty.']
>>> f.clean({'filename': 'name', 'content':''})
Traceback (most recent call last):
...
ValidationError: [u'The submitted file is empty.']
>>> type(f.clean({'filename': 'name', 'content':'Some File Content'}))
<class 'django.newforms.fields.UploadedFile'>
# URLField ################################################################## # URLField ##################################################################
>>> f = URLField() >>> f = URLField()
@ -2573,7 +2611,7 @@ Instances of a dynamic Form do not persist fields from one Form instance to
the next. the next.
>>> class MyForm(Form): >>> class MyForm(Form):
... def __init__(self, data=None, auto_id=False, field_list=[]): ... def __init__(self, data=None, auto_id=False, field_list=[]):
... Form.__init__(self, data, auto_id) ... Form.__init__(self, data, auto_id=auto_id)
... for field in field_list: ... for field in field_list:
... self.fields[field[0]] = field[1] ... self.fields[field[0]] = field[1]
>>> field_list = [('field1', CharField()), ('field2', CharField())] >>> field_list = [('field1', CharField()), ('field2', CharField())]
@ -2591,7 +2629,7 @@ the next.
... default_field_1 = CharField() ... default_field_1 = CharField()
... default_field_2 = CharField() ... default_field_2 = CharField()
... def __init__(self, data=None, auto_id=False, field_list=[]): ... def __init__(self, data=None, auto_id=False, field_list=[]):
... Form.__init__(self, data, auto_id) ... Form.__init__(self, data, auto_id=auto_id)
... for field in field_list: ... for field in field_list:
... self.fields[field[0]] = field[1] ... self.fields[field[0]] = field[1]
>>> field_list = [('field1', CharField()), ('field2', CharField())] >>> field_list = [('field1', CharField()), ('field2', CharField())]
@ -3246,6 +3284,35 @@ is different than its data. This is handled transparently, though.
<option value="3" selected="selected">No</option> <option value="3" selected="selected">No</option>
</select> </select>
# Forms with FileFields ################################################
FileFields are a special case because they take their data from the request.FILES,
not request.POST.
>>> class FileForm(Form):
... file1 = FileField()
>>> f = FileForm(auto_id=False)
>>> print f
<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>
>>> f = FileForm(data={}, files={}, auto_id=False)
>>> print f
<tr><th>File1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="file" name="file1" /></td></tr>
>>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':''}}, auto_id=False)
>>> print f
<tr><th>File1:</th><td><ul class="errorlist"><li>The submitted file is empty.</li></ul><input type="file" name="file1" /></td></tr>
>>> f = FileForm(data={}, files={'file1': 'something that is not a file'}, auto_id=False)
>>> print f
<tr><th>File1:</th><td><ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul><input type="file" name="file1" /></td></tr>
>>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':'some content'}}, auto_id=False)
>>> print f
<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>
>>> f.is_valid()
True
# Basic form processing in a view ############################################# # Basic form processing in a view #############################################
>>> from django.template import Template, Context >>> from django.template import Template, Context

Some files were not shown because too many files have changed in this diff Show More