web/lib/django/forms/models.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     1 """
     1 """
     2 Helper functions for creating Form classes from Django models
     2 Helper functions for creating Form classes from Django models
     3 and database field objects.
     3 and database field objects.
     4 """
     4 """
     5 
     5 
       
     6 from django.db import connections
     6 from django.utils.encoding import smart_unicode, force_unicode
     7 from django.utils.encoding import smart_unicode, force_unicode
     7 from django.utils.datastructures import SortedDict
     8 from django.utils.datastructures import SortedDict
     8 from django.utils.text import get_text_list, capfirst
     9 from django.utils.text import get_text_list, capfirst
     9 from django.utils.translation import ugettext_lazy as _, ugettext
    10 from django.utils.translation import ugettext_lazy as _, ugettext
    10 
    11 
    11 from util import ValidationError, ErrorList
    12 from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
    12 from forms import BaseForm, get_declared_fields, NON_FIELD_ERRORS
    13 from django.core.validators import EMPTY_VALUES
    13 from fields import Field, ChoiceField, IntegerField, EMPTY_VALUES
    14 from util import ErrorList
    14 from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput
    15 from forms import BaseForm, get_declared_fields
       
    16 from fields import Field, ChoiceField
       
    17 from widgets import SelectMultiple, HiddenInput, MultipleHiddenInput
    15 from widgets import media_property
    18 from widgets import media_property
    16 from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME
    19 from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME
    17 
       
    18 try:
       
    19     set
       
    20 except NameError:
       
    21     from sets import Set as set     # Python 2.3 fallback
       
    22 
    20 
    23 __all__ = (
    21 __all__ = (
    24     'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model',
    22     'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model',
    25     'save_instance', 'form_for_fields', 'ModelChoiceField',
    23     'save_instance', 'form_for_fields', 'ModelChoiceField',
    26     'ModelMultipleChoiceField',
    24     'ModelMultipleChoiceField',
    27 )
    25 )
    28 
    26 
    29 
    27 def construct_instance(form, instance, fields=None, exclude=None):
    30 def save_instance(form, instance, fields=None, fail_message='saved',
    28     """
    31                   commit=True, exclude=None):
    29     Constructs and returns a model instance from the bound ``form``'s
    32     """
    30     ``cleaned_data``, but does not save the returned instance to the
    33     Saves bound Form ``form``'s cleaned_data into model instance ``instance``.
    31     database.
    34 
       
    35     If commit=True, then the changes to ``instance`` will be saved to the
       
    36     database. Returns ``instance``.
       
    37     """
    32     """
    38     from django.db import models
    33     from django.db import models
    39     opts = instance._meta
    34     opts = instance._meta
    40     if form.errors:
    35 
    41         raise ValueError("The %s could not be %s because the data didn't"
       
    42                          " validate." % (opts.object_name, fail_message))
       
    43     cleaned_data = form.cleaned_data
    36     cleaned_data = form.cleaned_data
    44     file_field_list = []
    37     file_field_list = []
    45     for f in opts.fields:
    38     for f in opts.fields:
    46         if not f.editable or isinstance(f, models.AutoField) \
    39         if not f.editable or isinstance(f, models.AutoField) \
    47                 or not f.name in cleaned_data:
    40                 or not f.name in cleaned_data:
    48             continue
    41             continue
    49         if fields and f.name not in fields:
    42         if fields and f.name not in fields:
    50             continue
    43             continue
    51         if exclude and f.name in exclude:
    44         if exclude and f.name in exclude:
    52             continue
    45             continue
    53         # OneToOneField doesn't allow assignment of None. Guard against that
       
    54         # instead of allowing it and throwing an error.
       
    55         if isinstance(f, models.OneToOneField) and cleaned_data[f.name] is None:
       
    56             continue
       
    57         # Defer saving file-type fields until after the other fields, so a
    46         # Defer saving file-type fields until after the other fields, so a
    58         # callable upload_to can use the values from other fields.
    47         # callable upload_to can use the values from other fields.
    59         if isinstance(f, models.FileField):
    48         if isinstance(f, models.FileField):
    60             file_field_list.append(f)
    49             file_field_list.append(f)
    61         else:
    50         else:
    62             f.save_form_data(instance, cleaned_data[f.name])
    51             f.save_form_data(instance, cleaned_data[f.name])
    63 
    52 
    64     for f in file_field_list:
    53     for f in file_field_list:
    65         f.save_form_data(instance, cleaned_data[f.name])
    54         f.save_form_data(instance, cleaned_data[f.name])
    66 
    55 
       
    56     return instance
       
    57 
       
    58 def save_instance(form, instance, fields=None, fail_message='saved',
       
    59                   commit=True, exclude=None, construct=True):
       
    60     """
       
    61     Saves bound Form ``form``'s cleaned_data into model instance ``instance``.
       
    62 
       
    63     If commit=True, then the changes to ``instance`` will be saved to the
       
    64     database. Returns ``instance``.
       
    65 
       
    66     If construct=False, assume ``instance`` has already been constructed and
       
    67     just needs to be saved.
       
    68     """
       
    69     if construct:
       
    70         instance = construct_instance(form, instance, fields, exclude)
       
    71     opts = instance._meta
       
    72     if form.errors:
       
    73         raise ValueError("The %s could not be %s because the data didn't"
       
    74                          " validate." % (opts.object_name, fail_message))
       
    75 
    67     # Wrap up the saving of m2m data as a function.
    76     # Wrap up the saving of m2m data as a function.
    68     def save_m2m():
    77     def save_m2m():
    69         opts = instance._meta
       
    70         cleaned_data = form.cleaned_data
    78         cleaned_data = form.cleaned_data
    71         for f in opts.many_to_many:
    79         for f in opts.many_to_many:
    72             if fields and f.name not in fields:
    80             if fields and f.name not in fields:
    73                 continue
    81                 continue
    74             if f.name in cleaned_data:
    82             if f.name in cleaned_data:
   117     ``exclude`` is an optional list of field names. If provided, the named
   125     ``exclude`` is an optional list of field names. If provided, the named
   118     fields will be excluded from the returned dict, even if they are listed in
   126     fields will be excluded from the returned dict, even if they are listed in
   119     the ``fields`` argument.
   127     the ``fields`` argument.
   120     """
   128     """
   121     # avoid a circular import
   129     # avoid a circular import
   122     from django.db.models.fields.related import ManyToManyField, OneToOneField
   130     from django.db.models.fields.related import ManyToManyField
   123     opts = instance._meta
   131     opts = instance._meta
   124     data = {}
   132     data = {}
   125     for f in opts.fields + opts.many_to_many:
   133     for f in opts.fields + opts.many_to_many:
   126         if not f.editable:
   134         if not f.editable:
   127             continue
   135             continue
   140                 data[f.name] = [obj.pk for obj in f.value_from_object(instance)]
   148                 data[f.name] = [obj.pk for obj in f.value_from_object(instance)]
   141         else:
   149         else:
   142             data[f.name] = f.value_from_object(instance)
   150             data[f.name] = f.value_from_object(instance)
   143     return data
   151     return data
   144 
   152 
   145 def fields_for_model(model, fields=None, exclude=None, formfield_callback=lambda f: f.formfield()):
   153 def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
   146     """
   154     """
   147     Returns a ``SortedDict`` containing form fields for the given model.
   155     Returns a ``SortedDict`` containing form fields for the given model.
   148 
   156 
   149     ``fields`` is an optional list of field names. If provided, only the named
   157     ``fields`` is an optional list of field names. If provided, only the named
   150     fields will be included in the returned fields.
   158     fields will be included in the returned fields.
   152     ``exclude`` is an optional list of field names. If provided, the named
   160     ``exclude`` is an optional list of field names. If provided, the named
   153     fields will be excluded from the returned fields, even if they are listed
   161     fields will be excluded from the returned fields, even if they are listed
   154     in the ``fields`` argument.
   162     in the ``fields`` argument.
   155     """
   163     """
   156     field_list = []
   164     field_list = []
       
   165     ignored = []
   157     opts = model._meta
   166     opts = model._meta
   158     for f in opts.fields + opts.many_to_many:
   167     for f in opts.fields + opts.many_to_many:
   159         if not f.editable:
   168         if not f.editable:
   160             continue
   169             continue
   161         if fields and not f.name in fields:
   170         if fields and not f.name in fields:
   162             continue
   171             continue
   163         if exclude and f.name in exclude:
   172         if exclude and f.name in exclude:
   164             continue
   173             continue
   165         formfield = formfield_callback(f)
   174         if widgets and f.name in widgets:
       
   175             kwargs = {'widget': widgets[f.name]}
       
   176         else:
       
   177             kwargs = {}
       
   178         formfield = formfield_callback(f, **kwargs)
   166         if formfield:
   179         if formfield:
   167             field_list.append((f.name, formfield))
   180             field_list.append((f.name, formfield))
       
   181         else:
       
   182             ignored.append(f.name)
   168     field_dict = SortedDict(field_list)
   183     field_dict = SortedDict(field_list)
   169     if fields:
   184     if fields:
   170         field_dict = SortedDict([(f, field_dict.get(f)) for f in fields if (not exclude) or (exclude and f not in exclude)])
   185         field_dict = SortedDict(
       
   186             [(f, field_dict.get(f)) for f in fields
       
   187                 if ((not exclude) or (exclude and f not in exclude)) and (f not in ignored)]
       
   188         )
   171     return field_dict
   189     return field_dict
   172 
   190 
   173 class ModelFormOptions(object):
   191 class ModelFormOptions(object):
   174     def __init__(self, options=None):
   192     def __init__(self, options=None):
   175         self.model = getattr(options, 'model', None)
   193         self.model = getattr(options, 'model', None)
   176         self.fields = getattr(options, 'fields', None)
   194         self.fields = getattr(options, 'fields', None)
   177         self.exclude = getattr(options, 'exclude', None)
   195         self.exclude = getattr(options, 'exclude', None)
       
   196         self.widgets = getattr(options, 'widgets', None)
   178 
   197 
   179 
   198 
   180 class ModelFormMetaclass(type):
   199 class ModelFormMetaclass(type):
   181     def __new__(cls, name, bases, attrs):
   200     def __new__(cls, name, bases, attrs):
   182         formfield_callback = attrs.pop('formfield_callback',
   201         formfield_callback = attrs.pop('formfield_callback',
   183                 lambda f: f.formfield())
   202                 lambda f, **kwargs: f.formfield(**kwargs))
   184         try:
   203         try:
   185             parents = [b for b in bases if issubclass(b, ModelForm)]
   204             parents = [b for b in bases if issubclass(b, ModelForm)]
   186         except NameError:
   205         except NameError:
   187             # We are defining ModelForm itself.
   206             # We are defining ModelForm itself.
   188             parents = None
   207             parents = None
   196             new_class.media = media_property(new_class)
   215             new_class.media = media_property(new_class)
   197         opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))
   216         opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))
   198         if opts.model:
   217         if opts.model:
   199             # If a model is defined, extract form fields from it.
   218             # If a model is defined, extract form fields from it.
   200             fields = fields_for_model(opts.model, opts.fields,
   219             fields = fields_for_model(opts.model, opts.fields,
   201                                       opts.exclude, formfield_callback)
   220                                       opts.exclude, opts.widgets, formfield_callback)
   202             # Override default model fields with any custom declared ones
   221             # Override default model fields with any custom declared ones
   203             # (plus, include all the other declared fields).
   222             # (plus, include all the other declared fields).
   204             fields.update(declared_fields)
   223             fields.update(declared_fields)
   205         else:
   224         else:
   206             fields = declared_fields
   225             fields = declared_fields
   212     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
   231     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
   213                  initial=None, error_class=ErrorList, label_suffix=':',
   232                  initial=None, error_class=ErrorList, label_suffix=':',
   214                  empty_permitted=False, instance=None):
   233                  empty_permitted=False, instance=None):
   215         opts = self._meta
   234         opts = self._meta
   216         if instance is None:
   235         if instance is None:
       
   236             if opts.model is None:
       
   237                 raise ValueError('ModelForm has no model class specified.')
   217             # if we didn't get an instance, instantiate a new one
   238             # if we didn't get an instance, instantiate a new one
   218             self.instance = opts.model()
   239             self.instance = opts.model()
   219             object_data = {}
   240             object_data = {}
       
   241             self.instance._adding = True
   220         else:
   242         else:
   221             self.instance = instance
   243             self.instance = instance
       
   244             self.instance._adding = False
   222             object_data = model_to_dict(instance, opts.fields, opts.exclude)
   245             object_data = model_to_dict(instance, opts.fields, opts.exclude)
   223         # if initial was provided, it should override the values from instance
   246         # if initial was provided, it should override the values from instance
   224         if initial is not None:
   247         if initial is not None:
   225             object_data.update(initial)
   248             object_data.update(initial)
       
   249         # self._validate_unique will be set to True by BaseModelForm.clean().
       
   250         # It is False by default so overriding self.clean() and failing to call
       
   251         # super will stop validate_unique from being called.
       
   252         self._validate_unique = False
   226         super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
   253         super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
   227                                             error_class, label_suffix, empty_permitted)
   254                                             error_class, label_suffix, empty_permitted)
   228 
   255 
       
   256     def _update_errors(self, message_dict):
       
   257         for k, v in message_dict.items():
       
   258             if k != NON_FIELD_ERRORS:
       
   259                 self._errors.setdefault(k, self.error_class()).extend(v)
       
   260                 # Remove the data from the cleaned_data dict since it was invalid
       
   261                 if k in self.cleaned_data:
       
   262                     del self.cleaned_data[k]
       
   263         if NON_FIELD_ERRORS in message_dict:
       
   264             messages = message_dict[NON_FIELD_ERRORS]
       
   265             self._errors.setdefault(NON_FIELD_ERRORS, self.error_class()).extend(messages)
       
   266 
       
   267     def _get_validation_exclusions(self):
       
   268         """
       
   269         For backwards-compatibility, several types of fields need to be
       
   270         excluded from model validation. See the following tickets for
       
   271         details: #12507, #12521, #12553
       
   272         """
       
   273         exclude = []
       
   274         # Build up a list of fields that should be excluded from model field
       
   275         # validation and unique checks.
       
   276         for f in self.instance._meta.fields:
       
   277             field = f.name
       
   278             # Exclude fields that aren't on the form. The developer may be
       
   279             # adding these values to the model after form validation.
       
   280             if field not in self.fields:
       
   281                 exclude.append(f.name)
       
   282 
       
   283             # Don't perform model validation on fields that were defined
       
   284             # manually on the form and excluded via the ModelForm's Meta
       
   285             # class. See #12901.
       
   286             elif self._meta.fields and field not in self._meta.fields:
       
   287                 exclude.append(f.name)
       
   288             elif self._meta.exclude and field in self._meta.exclude:
       
   289                 exclude.append(f.name)
       
   290 
       
   291             # Exclude fields that failed form validation. There's no need for
       
   292             # the model fields to validate them as well.
       
   293             elif field in self._errors.keys():
       
   294                 exclude.append(f.name)
       
   295 
       
   296             # Exclude empty fields that are not required by the form, if the
       
   297             # underlying model field is required. This keeps the model field
       
   298             # from raising a required error. Note: don't exclude the field from
       
   299             # validaton if the model field allows blanks. If it does, the blank
       
   300             # value may be included in a unique check, so cannot be excluded
       
   301             # from validation.
       
   302             else:
       
   303                 form_field = self.fields[field]
       
   304                 field_value = self.cleaned_data.get(field, None)
       
   305                 if not f.blank and not form_field.required and field_value in EMPTY_VALUES:
       
   306                     exclude.append(f.name)
       
   307         return exclude
       
   308 
   229     def clean(self):
   309     def clean(self):
   230         self.validate_unique()
   310         self._validate_unique = True
   231         return self.cleaned_data
   311         return self.cleaned_data
   232 
   312 
       
   313     def _post_clean(self):
       
   314         opts = self._meta
       
   315         # Update the model instance with self.cleaned_data.
       
   316         self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
       
   317 
       
   318         exclude = self._get_validation_exclusions()
       
   319 
       
   320         # Foreign Keys being used to represent inline relationships
       
   321         # are excluded from basic field value validation. This is for two
       
   322         # reasons: firstly, the value may not be supplied (#12507; the
       
   323         # case of providing new values to the admin); secondly the
       
   324         # object being referred to may not yet fully exist (#12749).
       
   325         # However, these fields *must* be included in uniqueness checks,
       
   326         # so this can't be part of _get_validation_exclusions().
       
   327         for f_name, field in self.fields.items():
       
   328             if isinstance(field, InlineForeignKeyField):
       
   329                 exclude.append(f_name)
       
   330 
       
   331         # Clean the model instance's fields.
       
   332         try:
       
   333             self.instance.clean_fields(exclude=exclude)
       
   334         except ValidationError, e:
       
   335             self._update_errors(e.message_dict)
       
   336 
       
   337         # Call the model instance's clean method.
       
   338         try:
       
   339             self.instance.clean()
       
   340         except ValidationError, e:
       
   341             self._update_errors({NON_FIELD_ERRORS: e.messages})
       
   342 
       
   343         # Validate uniqueness if needed.
       
   344         if self._validate_unique:
       
   345             self.validate_unique()
       
   346 
   233     def validate_unique(self):
   347     def validate_unique(self):
   234         unique_checks, date_checks = self._get_unique_checks()
   348         """
   235         form_errors = []
   349         Calls the instance's validate_unique() method and updates the form's
   236         bad_fields = set()
   350         validation errors if any were raised.
   237 
   351         """
   238         field_errors, global_errors = self._perform_unique_checks(unique_checks)
   352         exclude = self._get_validation_exclusions()
   239         bad_fields.union(field_errors)
   353         try:
   240         form_errors.extend(global_errors)
   354             self.instance.validate_unique(exclude=exclude)
   241 
   355         except ValidationError, e:
   242         field_errors, global_errors = self._perform_date_checks(date_checks)
   356             self._update_errors(e.message_dict)
   243         bad_fields.union(field_errors)
       
   244         form_errors.extend(global_errors)
       
   245 
       
   246         for field_name in bad_fields:
       
   247             del self.cleaned_data[field_name]
       
   248         if form_errors:
       
   249             # Raise the unique together errors since they are considered
       
   250             # form-wide.
       
   251             raise ValidationError(form_errors)
       
   252 
       
   253     def _get_unique_checks(self):
       
   254         from django.db.models.fields import FieldDoesNotExist, Field as ModelField
       
   255 
       
   256         # Gather a list of checks to perform. We only perform unique checks
       
   257         # for fields present and not None in cleaned_data.  Since this is a
       
   258         # ModelForm, some fields may have been excluded; we can't perform a unique
       
   259         # check on a form that is missing fields involved in that check.  It also does
       
   260         # not make sense to check data that didn't validate, and since NULL does not
       
   261         # equal NULL in SQL we should not do any unique checking for NULL values.
       
   262         unique_checks = []
       
   263         # these are checks for the unique_for_<date/year/month>
       
   264         date_checks = []
       
   265         for check in self.instance._meta.unique_together[:]:
       
   266             fields_on_form = [field for field in check if self.cleaned_data.get(field) is not None]
       
   267             if len(fields_on_form) == len(check):
       
   268                 unique_checks.append(check)
       
   269 
       
   270         # Gather a list of checks for fields declared as unique and add them to
       
   271         # the list of checks. Again, skip empty fields and any that did not validate.
       
   272         for name in self.fields:
       
   273             try:
       
   274                 f = self.instance._meta.get_field_by_name(name)[0]
       
   275             except FieldDoesNotExist:
       
   276                 # This is an extra field that's not on the ModelForm, ignore it
       
   277                 continue
       
   278             if not isinstance(f, ModelField):
       
   279                 # This is an extra field that happens to have a name that matches,
       
   280                 # for example, a related object accessor for this model.  So
       
   281                 # get_field_by_name found it, but it is not a Field so do not proceed
       
   282                 # to use it as if it were.
       
   283                 continue
       
   284             if self.cleaned_data.get(name) is None:
       
   285                 continue
       
   286             if f.unique:
       
   287                 unique_checks.append((name,))
       
   288             if f.unique_for_date and self.cleaned_data.get(f.unique_for_date) is not None:
       
   289                 date_checks.append(('date', name, f.unique_for_date))
       
   290             if f.unique_for_year and self.cleaned_data.get(f.unique_for_year) is not None:
       
   291                 date_checks.append(('year', name, f.unique_for_year))
       
   292             if f.unique_for_month and self.cleaned_data.get(f.unique_for_month) is not None:
       
   293                 date_checks.append(('month', name, f.unique_for_month))
       
   294         return unique_checks, date_checks
       
   295 
       
   296 
       
   297     def _perform_unique_checks(self, unique_checks):
       
   298         bad_fields = set()
       
   299         form_errors = []
       
   300 
       
   301         for unique_check in unique_checks:
       
   302             # Try to look up an existing object with the same values as this
       
   303             # object's values for all the unique field.
       
   304 
       
   305             lookup_kwargs = {}
       
   306             for field_name in unique_check:
       
   307                 lookup_value = self.cleaned_data[field_name]
       
   308                 # ModelChoiceField will return an object instance rather than
       
   309                 # a raw primary key value, so convert it to a pk value before
       
   310                 # using it in a lookup.
       
   311                 if isinstance(self.fields[field_name], ModelChoiceField):
       
   312                     lookup_value =  lookup_value.pk
       
   313                 lookup_kwargs[str(field_name)] = lookup_value
       
   314 
       
   315             qs = self.instance.__class__._default_manager.filter(**lookup_kwargs)
       
   316 
       
   317             # Exclude the current object from the query if we are editing an
       
   318             # instance (as opposed to creating a new one)
       
   319             if self.instance.pk is not None:
       
   320                 qs = qs.exclude(pk=self.instance.pk)
       
   321 
       
   322             # This cute trick with extra/values is the most efficient way to
       
   323             # tell if a particular query returns any results.
       
   324             if qs.extra(select={'a': 1}).values('a').order_by():
       
   325                 if len(unique_check) == 1:
       
   326                     self._errors[unique_check[0]] = ErrorList([self.unique_error_message(unique_check)])
       
   327                 else:
       
   328                     form_errors.append(self.unique_error_message(unique_check))
       
   329 
       
   330                 # Mark these fields as needing to be removed from cleaned data
       
   331                 # later.
       
   332                 for field_name in unique_check:
       
   333                     bad_fields.add(field_name)
       
   334         return bad_fields, form_errors
       
   335 
       
   336     def _perform_date_checks(self, date_checks):
       
   337         bad_fields = set()
       
   338         for lookup_type, field, unique_for in date_checks:
       
   339             lookup_kwargs = {}
       
   340             # there's a ticket to add a date lookup, we can remove this special
       
   341             # case if that makes it's way in
       
   342             if lookup_type == 'date':
       
   343                 date = self.cleaned_data[unique_for]
       
   344                 lookup_kwargs['%s__day' % unique_for] = date.day
       
   345                 lookup_kwargs['%s__month' % unique_for] = date.month
       
   346                 lookup_kwargs['%s__year' % unique_for] = date.year
       
   347             else:
       
   348                 lookup_kwargs['%s__%s' % (unique_for, lookup_type)] = getattr(self.cleaned_data[unique_for], lookup_type)
       
   349             lookup_kwargs[field] = self.cleaned_data[field]
       
   350 
       
   351             qs = self.instance.__class__._default_manager.filter(**lookup_kwargs)
       
   352             # Exclude the current object from the query if we are editing an
       
   353             # instance (as opposed to creating a new one)
       
   354             if self.instance.pk is not None:
       
   355                 qs = qs.exclude(pk=self.instance.pk)
       
   356 
       
   357             # This cute trick with extra/values is the most efficient way to
       
   358             # tell if a particular query returns any results.
       
   359             if qs.extra(select={'a': 1}).values('a').order_by():
       
   360                 self._errors[field] = ErrorList([
       
   361                     self.date_error_message(lookup_type, field, unique_for)
       
   362                 ])
       
   363                 bad_fields.add(field)
       
   364         return bad_fields, []
       
   365 
       
   366     def date_error_message(self, lookup_type, field, unique_for):
       
   367         return _(u"%(field_name)s must be unique for %(date_field)s %(lookup)s.") % {
       
   368             'field_name': unicode(self.fields[field].label),
       
   369             'date_field': unicode(self.fields[unique_for].label),
       
   370             'lookup': lookup_type,
       
   371         }
       
   372 
       
   373     def unique_error_message(self, unique_check):
       
   374         model_name = capfirst(self.instance._meta.verbose_name)
       
   375 
       
   376         # A unique field
       
   377         if len(unique_check) == 1:
       
   378             field_name = unique_check[0]
       
   379             field_label = self.fields[field_name].label
       
   380             # Insert the error into the error dict, very sneaky
       
   381             return _(u"%(model_name)s with this %(field_label)s already exists.") %  {
       
   382                 'model_name': unicode(model_name),
       
   383                 'field_label': unicode(field_label)
       
   384             }
       
   385         # unique_together
       
   386         else:
       
   387             field_labels = [self.fields[field_name].label for field_name in unique_check]
       
   388             field_labels = get_text_list(field_labels, _('and'))
       
   389             return _(u"%(model_name)s with this %(field_label)s already exists.") %  {
       
   390                 'model_name': unicode(model_name),
       
   391                 'field_label': unicode(field_labels)
       
   392             }
       
   393 
   357 
   394     def save(self, commit=True):
   358     def save(self, commit=True):
   395         """
   359         """
   396         Saves this ``form``'s cleaned_data into model instance
   360         Saves this ``form``'s cleaned_data into model instance
   397         ``self.instance``.
   361         ``self.instance``.
   402         if self.instance.pk is None:
   366         if self.instance.pk is None:
   403             fail_message = 'created'
   367             fail_message = 'created'
   404         else:
   368         else:
   405             fail_message = 'changed'
   369             fail_message = 'changed'
   406         return save_instance(self, self.instance, self._meta.fields,
   370         return save_instance(self, self.instance, self._meta.fields,
   407                              fail_message, commit, exclude=self._meta.exclude)
   371                              fail_message, commit, construct=False)
   408 
   372 
   409     save.alters_data = True
   373     save.alters_data = True
   410 
   374 
   411 class ModelForm(BaseModelForm):
   375 class ModelForm(BaseModelForm):
   412     __metaclass__ = ModelFormMetaclass
   376     __metaclass__ = ModelFormMetaclass
   472     def _construct_form(self, i, **kwargs):
   436     def _construct_form(self, i, **kwargs):
   473         if self.is_bound and i < self.initial_form_count():
   437         if self.is_bound and i < self.initial_form_count():
   474             pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
   438             pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
   475             pk = self.data[pk_key]
   439             pk = self.data[pk_key]
   476             pk_field = self.model._meta.pk
   440             pk_field = self.model._meta.pk
   477             pk = pk_field.get_db_prep_lookup('exact', pk)
   441             pk = pk_field.get_db_prep_lookup('exact', pk,
       
   442                 connection=connections[self.get_queryset().db])
   478             if isinstance(pk, list):
   443             if isinstance(pk, list):
   479                 pk = pk[0]
   444                 pk = pk[0]
   480             kwargs['instance'] = self._existing_object(pk)
   445             kwargs['instance'] = self._existing_object(pk)
   481         if i < self.initial_form_count() and not kwargs.get('instance'):
   446         if i < self.initial_form_count() and not kwargs.get('instance'):
   482             kwargs['instance'] = self.get_queryset()[i]
   447             kwargs['instance'] = self.get_queryset()[i]
   493             # artificial ordering here to make sure that all formsets
   458             # artificial ordering here to make sure that all formsets
   494             # constructed from this queryset have the same form order.
   459             # constructed from this queryset have the same form order.
   495             if not qs.ordered:
   460             if not qs.ordered:
   496                 qs = qs.order_by(self.model._meta.pk.name)
   461                 qs = qs.order_by(self.model._meta.pk.name)
   497 
   462 
   498             if self.max_num > 0:
   463             # Removed queryset limiting here. As per discussion re: #13023
   499                 self._queryset = qs[:self.max_num]
   464             # on django-dev, max_num should not prevent existing
   500             else:
   465             # related objects/inlines from being displayed.
   501                 self._queryset = qs
   466             self._queryset = qs
   502         return self._queryset
   467         return self._queryset
   503 
   468 
   504     def save_new(self, form, commit=True):
   469     def save_new(self, form, commit=True):
   505         """Saves and returns a new model instance for the given form."""
   470         """Saves and returns a new model instance for the given form."""
   506         return form.save(commit=commit)
   471         return form.save(commit=commit)
   523 
   488 
   524     def clean(self):
   489     def clean(self):
   525         self.validate_unique()
   490         self.validate_unique()
   526 
   491 
   527     def validate_unique(self):
   492     def validate_unique(self):
   528         # Iterate over the forms so that we can find one with potentially valid
   493         # Collect unique_checks and date_checks to run from all the forms.
   529         # data from which to extract the error checks
   494         all_unique_checks = set()
       
   495         all_date_checks = set()
   530         for form in self.forms:
   496         for form in self.forms:
   531             if hasattr(form, 'cleaned_data'):
   497             if not hasattr(form, 'cleaned_data'):
   532                 break
   498                 continue
   533         else:
   499             exclude = form._get_validation_exclusions()
   534             return
   500             unique_checks, date_checks = form.instance._get_unique_checks(exclude=exclude)
   535         unique_checks, date_checks = form._get_unique_checks()
   501             all_unique_checks = all_unique_checks.union(set(unique_checks))
       
   502             all_date_checks = all_date_checks.union(set(date_checks))
       
   503 
   536         errors = []
   504         errors = []
   537         # Do each of the unique checks (unique and unique_together)
   505         # Do each of the unique checks (unique and unique_together)
   538         for unique_check in unique_checks:
   506         for uclass, unique_check in all_unique_checks:
   539             seen_data = set()
   507             seen_data = set()
   540             for form in self.forms:
   508             for form in self.forms:
   541                 # if the form doesn't have cleaned_data then we ignore it,
   509                 # if the form doesn't have cleaned_data then we ignore it,
   542                 # it's already invalid
   510                 # it's already invalid
   543                 if not hasattr(form, "cleaned_data"):
   511                 if not hasattr(form, "cleaned_data"):
   555                         del form.cleaned_data
   523                         del form.cleaned_data
   556                         break
   524                         break
   557                     # mark the data as seen
   525                     # mark the data as seen
   558                     seen_data.add(row_data)
   526                     seen_data.add(row_data)
   559         # iterate over each of the date checks now
   527         # iterate over each of the date checks now
   560         for date_check in date_checks:
   528         for date_check in all_date_checks:
   561             seen_data = set()
   529             seen_data = set()
   562             lookup, field, unique_for = date_check
   530             uclass, lookup, field, unique_for = date_check
   563             for form in self.forms:
   531             for form in self.forms:
   564                 # if the form doesn't have cleaned_data then we ignore it,
   532                 # if the form doesn't have cleaned_data then we ignore it,
   565                 # it's already invalid
   533                 # it's already invalid
   566                 if not hasattr(self, 'cleaned_data'):
   534                 if not hasattr(self, 'cleaned_data'):
   567                     continue
   535                     continue
   601                 }
   569                 }
   602 
   570 
   603     def get_date_error_message(self, date_check):
   571     def get_date_error_message(self, date_check):
   604         return ugettext("Please correct the duplicate data for %(field_name)s "
   572         return ugettext("Please correct the duplicate data for %(field_name)s "
   605             "which must be unique for the %(lookup)s in %(date_field)s.") % {
   573             "which must be unique for the %(lookup)s in %(date_field)s.") % {
   606             'field_name': date_check[1],
   574             'field_name': date_check[2],
   607             'date_field': date_check[2],
   575             'date_field': date_check[3],
   608             'lookup': unicode(date_check[0]),
   576             'lookup': unicode(date_check[1]),
   609         }
   577         }
   610 
   578 
   611     def get_form_error(self):
   579     def get_form_error(self):
   612         return ugettext("Please correct the duplicate values below.")
   580         return ugettext("Please correct the duplicate values below.")
   613 
   581 
   674         if pk_is_not_editable(pk) or pk.name not in form.fields:
   642         if pk_is_not_editable(pk) or pk.name not in form.fields:
   675             if form.is_bound:
   643             if form.is_bound:
   676                 pk_value = form.instance.pk
   644                 pk_value = form.instance.pk
   677             else:
   645             else:
   678                 try:
   646                 try:
   679                     pk_value = self.get_queryset()[index].pk
   647                     if index is not None:
       
   648                         pk_value = self.get_queryset()[index].pk
       
   649                     else:
       
   650                         pk_value = None
   680                 except IndexError:
   651                 except IndexError:
   681                     pk_value = None
   652                     pk_value = None
   682             if isinstance(pk, OneToOneField) or isinstance(pk, ForeignKey):
   653             if isinstance(pk, OneToOneField) or isinstance(pk, ForeignKey):
   683                 qs = pk.rel.to._default_manager.get_query_set()
   654                 qs = pk.rel.to._default_manager.get_query_set()
   684             else:
   655             else:
   685                 qs = self.model._default_manager.get_query_set()
   656                 qs = self.model._default_manager.get_query_set()
       
   657             qs = qs.using(form.instance._state.db)
   686             form.fields[self._pk_field.name] = ModelChoiceField(qs, initial=pk_value, required=False, widget=HiddenInput)
   658             form.fields[self._pk_field.name] = ModelChoiceField(qs, initial=pk_value, required=False, widget=HiddenInput)
   687         super(BaseModelFormSet, self).add_fields(form, index)
   659         super(BaseModelFormSet, self).add_fields(form, index)
   688 
   660 
   689 def modelformset_factory(model, form=ModelForm, formfield_callback=lambda f: f.formfield(),
   661 def modelformset_factory(model, form=ModelForm, formfield_callback=lambda f: f.formfield(),
   690                          formset=BaseModelFormSet,
   662                          formset=BaseModelFormSet,
   691                          extra=1, can_delete=False, can_order=False,
   663                          extra=1, can_delete=False, can_order=False,
   692                          max_num=0, fields=None, exclude=None):
   664                          max_num=None, fields=None, exclude=None):
   693     """
   665     """
   694     Returns a FormSet class for the given Django model class.
   666     Returns a FormSet class for the given Django model class.
   695     """
   667     """
   696     form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
   668     form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
   697                              formfield_callback=formfield_callback)
   669                              formfield_callback=formfield_callback)
   704 # InlineFormSets #############################################################
   676 # InlineFormSets #############################################################
   705 
   677 
   706 class BaseInlineFormSet(BaseModelFormSet):
   678 class BaseInlineFormSet(BaseModelFormSet):
   707     """A formset for child objects related to a parent."""
   679     """A formset for child objects related to a parent."""
   708     def __init__(self, data=None, files=None, instance=None,
   680     def __init__(self, data=None, files=None, instance=None,
   709                  save_as_new=False, prefix=None):
   681                  save_as_new=False, prefix=None, queryset=None):
   710         from django.db.models.fields.related import RelatedObject
   682         from django.db.models.fields.related import RelatedObject
   711         if instance is None:
   683         if instance is None:
   712             self.instance = self.model()
   684             self.instance = self.fk.rel.to()
   713         else:
   685         else:
   714             self.instance = instance
   686             self.instance = instance
   715         self.save_as_new = save_as_new
   687         self.save_as_new = save_as_new
   716         # is there a better way to get the object descriptor?
   688         # is there a better way to get the object descriptor?
   717         self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
   689         self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
   718         if self.fk.rel.field_name == self.fk.rel.to._meta.pk.name:
   690         if self.fk.rel.field_name == self.fk.rel.to._meta.pk.name:
   719             backlink_value = self.instance
   691             backlink_value = self.instance
   720         else:
   692         else:
   721             backlink_value = getattr(self.instance, self.fk.rel.field_name)
   693             backlink_value = getattr(self.instance, self.fk.rel.field_name)
   722         qs = self.model._default_manager.filter(**{self.fk.name: backlink_value})
   694         if queryset is None:
       
   695             queryset = self.model._default_manager
       
   696         qs = queryset.filter(**{self.fk.name: backlink_value})
   723         super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
   697         super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
   724                                                 queryset=qs)
   698                                                 queryset=qs)
   725 
   699 
   726     def initial_form_count(self):
   700     def initial_form_count(self):
   727         if self.save_as_new:
   701         if self.save_as_new:
   740             # creating new instances
   714             # creating new instances
   741             form.data[form.add_prefix(self._pk_field.name)] = None
   715             form.data[form.add_prefix(self._pk_field.name)] = None
   742 
   716 
   743             # Remove the foreign key from the form's data
   717             # Remove the foreign key from the form's data
   744             form.data[form.add_prefix(self.fk.name)] = None
   718             form.data[form.add_prefix(self.fk.name)] = None
       
   719 
       
   720         # Set the fk value here so that the form can do it's validation.
       
   721         setattr(form.instance, self.fk.get_attname(), self.instance.pk)
   745         return form
   722         return form
   746 
   723 
   747     #@classmethod
   724     #@classmethod
   748     def get_default_prefix(cls):
   725     def get_default_prefix(cls):
   749         from django.db.models.fields.related import RelatedObject
   726         from django.db.models.fields.related import RelatedObject
   750         return RelatedObject(cls.fk.rel.to, cls.model, cls.fk).get_accessor_name()
   727         return RelatedObject(cls.fk.rel.to, cls.model, cls.fk).get_accessor_name().replace('+','')
   751     get_default_prefix = classmethod(get_default_prefix)
   728     get_default_prefix = classmethod(get_default_prefix)
   752 
   729 
   753     def save_new(self, form, commit=True):
   730     def save_new(self, form, commit=True):
   754         # Use commit=False so we can assign the parent key afterwards, then
   731         # Use commit=False so we can assign the parent key afterwards, then
   755         # save the object.
   732         # save the object.
   764         return obj
   741         return obj
   765 
   742 
   766     def add_fields(self, form, index):
   743     def add_fields(self, form, index):
   767         super(BaseInlineFormSet, self).add_fields(form, index)
   744         super(BaseInlineFormSet, self).add_fields(form, index)
   768         if self._pk_field == self.fk:
   745         if self._pk_field == self.fk:
   769             form.fields[self._pk_field.name] = InlineForeignKeyField(self.instance, pk_field=True)
   746             name = self._pk_field.name
       
   747             kwargs = {'pk_field': True}
   770         else:
   748         else:
   771             # The foreign key field might not be on the form, so we poke at the
   749             # The foreign key field might not be on the form, so we poke at the
   772             # Model field to get the label, since we need that for error messages.
   750             # Model field to get the label, since we need that for error messages.
       
   751             name = self.fk.name
   773             kwargs = {
   752             kwargs = {
   774                 'label': getattr(form.fields.get(self.fk.name), 'label', capfirst(self.fk.verbose_name))
   753                 'label': getattr(form.fields.get(name), 'label', capfirst(self.fk.verbose_name))
   775             }
   754             }
   776             if self.fk.rel.field_name != self.fk.rel.to._meta.pk.name:
   755             if self.fk.rel.field_name != self.fk.rel.to._meta.pk.name:
   777                 kwargs['to_field'] = self.fk.rel.field_name
   756                 kwargs['to_field'] = self.fk.rel.field_name
   778             form.fields[self.fk.name] = InlineForeignKeyField(self.instance, **kwargs)
   757 
       
   758         form.fields[name] = InlineForeignKeyField(self.instance, **kwargs)
       
   759 
       
   760         # Add the generated field to form._meta.fields if it's defined to make
       
   761         # sure validation isn't skipped on that field.
       
   762         if form._meta.fields:
       
   763             if isinstance(form._meta.fields, tuple):
       
   764                 form._meta.fields = list(form._meta.fields)
       
   765             form._meta.fields.append(self.fk.name)
   779 
   766 
   780     def get_unique_error_message(self, unique_check):
   767     def get_unique_error_message(self, unique_check):
   781         unique_check = [field for field in unique_check if field != self.fk.name]
   768         unique_check = [field for field in unique_check if field != self.fk.name]
   782         return super(BaseInlineFormSet, self).get_unique_error_message(unique_check)
   769         return super(BaseInlineFormSet, self).get_unique_error_message(unique_check)
       
   770 
   783 
   771 
   784 def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
   772 def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
   785     """
   773     """
   786     Finds and returns the ForeignKey from model to parent if there is one
   774     Finds and returns the ForeignKey from model to parent if there is one
   787     (returns None if can_fail is True and no such field exists). If fk_name is
   775     (returns None if can_fail is True and no such field exists). If fk_name is
   822 
   810 
   823 
   811 
   824 def inlineformset_factory(parent_model, model, form=ModelForm,
   812 def inlineformset_factory(parent_model, model, form=ModelForm,
   825                           formset=BaseInlineFormSet, fk_name=None,
   813                           formset=BaseInlineFormSet, fk_name=None,
   826                           fields=None, exclude=None,
   814                           fields=None, exclude=None,
   827                           extra=3, can_order=False, can_delete=True, max_num=0,
   815                           extra=3, can_order=False, can_delete=True, max_num=None,
   828                           formfield_callback=lambda f: f.formfield()):
   816                           formfield_callback=lambda f: f.formfield()):
   829     """
   817     """
   830     Returns an ``InlineFormSet`` for the given kwargs.
   818     Returns an ``InlineFormSet`` for the given kwargs.
   831 
   819 
   832     You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey``
   820     You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey``
   912                 yield choice
   900                 yield choice
   913         else:
   901         else:
   914             for obj in self.queryset.all():
   902             for obj in self.queryset.all():
   915                 yield self.choice(obj)
   903                 yield self.choice(obj)
   916 
   904 
       
   905     def __len__(self):
       
   906         return len(self.queryset)
       
   907 
   917     def choice(self, obj):
   908     def choice(self, obj):
   918         if self.field.to_field_name:
   909         if self.field.to_field_name:
   919             key = obj.serializable_value(self.field.to_field_name)
   910             key = obj.serializable_value(self.field.to_field_name)
   920         else:
   911         else:
   921             key = obj.pk
   912             key = obj.pk
   945         Field.__init__(self, required, widget, label, initial, help_text,
   936         Field.__init__(self, required, widget, label, initial, help_text,
   946                        *args, **kwargs)
   937                        *args, **kwargs)
   947         self.queryset = queryset
   938         self.queryset = queryset
   948         self.choice_cache = None
   939         self.choice_cache = None
   949         self.to_field_name = to_field_name
   940         self.to_field_name = to_field_name
       
   941 
       
   942     def __deepcopy__(self, memo):
       
   943         result = super(ChoiceField, self).__deepcopy__(memo)
       
   944         # Need to force a new ModelChoiceIterator to be created, bug #11183
       
   945         result.queryset = result.queryset
       
   946         return result
   950 
   947 
   951     def _get_queryset(self):
   948     def _get_queryset(self):
   952         return self._queryset
   949         return self._queryset
   953 
   950 
   954     def _set_queryset(self, queryset):
   951     def _set_queryset(self, queryset):
   982         # the queryset.
   979         # the queryset.
   983         return ModelChoiceIterator(self)
   980         return ModelChoiceIterator(self)
   984 
   981 
   985     choices = property(_get_choices, ChoiceField._set_choices)
   982     choices = property(_get_choices, ChoiceField._set_choices)
   986 
   983 
   987     def clean(self, value):
   984     def to_python(self, value):
   988         Field.clean(self, value)
       
   989         if value in EMPTY_VALUES:
   985         if value in EMPTY_VALUES:
   990             return None
   986             return None
   991         try:
   987         try:
   992             key = self.to_field_name or 'pk'
   988             key = self.to_field_name or 'pk'
   993             value = self.queryset.get(**{key: value})
   989             value = self.queryset.get(**{key: value})
   994         except self.queryset.model.DoesNotExist:
   990         except self.queryset.model.DoesNotExist:
   995             raise ValidationError(self.error_messages['invalid_choice'])
   991             raise ValidationError(self.error_messages['invalid_choice'])
   996         return value
   992         return value
       
   993 
       
   994     def validate(self, value):
       
   995         return Field.validate(self, value)
   997 
   996 
   998 class ModelMultipleChoiceField(ModelChoiceField):
   997 class ModelMultipleChoiceField(ModelChoiceField):
   999     """A MultipleChoiceField whose choices are a model QuerySet."""
   998     """A MultipleChoiceField whose choices are a model QuerySet."""
  1000     widget = SelectMultiple
   999     widget = SelectMultiple
  1001     hidden_widget = MultipleHiddenInput
  1000     hidden_widget = MultipleHiddenInput