web/lib/django/forms/models.py
changeset 38 77b6da96e6f1
equal deleted inserted replaced
37:8d941af65caf 38:77b6da96e6f1
       
     1 """
       
     2 Helper functions for creating Form classes from Django models
       
     3 and database field objects.
       
     4 """
       
     5 
       
     6 from django.db import connections
       
     7 from django.utils.encoding import smart_unicode, force_unicode
       
     8 from django.utils.datastructures import SortedDict
       
     9 from django.utils.text import get_text_list, capfirst
       
    10 from django.utils.translation import ugettext_lazy as _, ugettext
       
    11 
       
    12 from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
       
    13 from django.core.validators import EMPTY_VALUES
       
    14 from util import ErrorList
       
    15 from forms import BaseForm, get_declared_fields
       
    16 from fields import Field, ChoiceField
       
    17 from widgets import SelectMultiple, HiddenInput, MultipleHiddenInput
       
    18 from widgets import media_property
       
    19 from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME
       
    20 
       
    21 __all__ = (
       
    22     'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model',
       
    23     'save_instance', 'form_for_fields', 'ModelChoiceField',
       
    24     'ModelMultipleChoiceField',
       
    25 )
       
    26 
       
    27 def construct_instance(form, instance, fields=None, exclude=None):
       
    28     """
       
    29     Constructs and returns a model instance from the bound ``form``'s
       
    30     ``cleaned_data``, but does not save the returned instance to the
       
    31     database.
       
    32     """
       
    33     from django.db import models
       
    34     opts = instance._meta
       
    35 
       
    36     cleaned_data = form.cleaned_data
       
    37     file_field_list = []
       
    38     for f in opts.fields:
       
    39         if not f.editable or isinstance(f, models.AutoField) \
       
    40                 or not f.name in cleaned_data:
       
    41             continue
       
    42         if fields and f.name not in fields:
       
    43             continue
       
    44         if exclude and f.name in exclude:
       
    45             continue
       
    46         # Defer saving file-type fields until after the other fields, so a
       
    47         # callable upload_to can use the values from other fields.
       
    48         if isinstance(f, models.FileField):
       
    49             file_field_list.append(f)
       
    50         else:
       
    51             f.save_form_data(instance, cleaned_data[f.name])
       
    52 
       
    53     for f in file_field_list:
       
    54         f.save_form_data(instance, cleaned_data[f.name])
       
    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 
       
    76     # Wrap up the saving of m2m data as a function.
       
    77     def save_m2m():
       
    78         cleaned_data = form.cleaned_data
       
    79         for f in opts.many_to_many:
       
    80             if fields and f.name not in fields:
       
    81                 continue
       
    82             if f.name in cleaned_data:
       
    83                 f.save_form_data(instance, cleaned_data[f.name])
       
    84     if commit:
       
    85         # If we are committing, save the instance and the m2m data immediately.
       
    86         instance.save()
       
    87         save_m2m()
       
    88     else:
       
    89         # We're not committing. Add a method to the form to allow deferred
       
    90         # saving of m2m data.
       
    91         form.save_m2m = save_m2m
       
    92     return instance
       
    93 
       
    94 def make_model_save(model, fields, fail_message):
       
    95     """Returns the save() method for a Form."""
       
    96     def save(self, commit=True):
       
    97         return save_instance(self, model(), fields, fail_message, commit)
       
    98     return save
       
    99 
       
   100 def make_instance_save(instance, fields, fail_message):
       
   101     """Returns the save() method for a Form."""
       
   102     def save(self, commit=True):
       
   103         return save_instance(self, instance, fields, fail_message, commit)
       
   104     return save
       
   105 
       
   106 def form_for_fields(field_list):
       
   107     """
       
   108     Returns a Form class for the given list of Django database field instances.
       
   109     """
       
   110     fields = SortedDict([(f.name, f.formfield())
       
   111                          for f in field_list if f.editable])
       
   112     return type('FormForFields', (BaseForm,), {'base_fields': fields})
       
   113 
       
   114 
       
   115 # ModelForms #################################################################
       
   116 
       
   117 def model_to_dict(instance, fields=None, exclude=None):
       
   118     """
       
   119     Returns a dict containing the data in ``instance`` suitable for passing as
       
   120     a Form's ``initial`` keyword argument.
       
   121 
       
   122     ``fields`` is an optional list of field names. If provided, only the named
       
   123     fields will be included in the returned dict.
       
   124 
       
   125     ``exclude`` is an optional list of field names. If provided, the named
       
   126     fields will be excluded from the returned dict, even if they are listed in
       
   127     the ``fields`` argument.
       
   128     """
       
   129     # avoid a circular import
       
   130     from django.db.models.fields.related import ManyToManyField
       
   131     opts = instance._meta
       
   132     data = {}
       
   133     for f in opts.fields + opts.many_to_many:
       
   134         if not f.editable:
       
   135             continue
       
   136         if fields and not f.name in fields:
       
   137             continue
       
   138         if exclude and f.name in exclude:
       
   139             continue
       
   140         if isinstance(f, ManyToManyField):
       
   141             # If the object doesn't have a primry key yet, just use an empty
       
   142             # list for its m2m fields. Calling f.value_from_object will raise
       
   143             # an exception.
       
   144             if instance.pk is None:
       
   145                 data[f.name] = []
       
   146             else:
       
   147                 # MultipleChoiceWidget needs a list of pks, not object instances.
       
   148                 data[f.name] = [obj.pk for obj in f.value_from_object(instance)]
       
   149         else:
       
   150             data[f.name] = f.value_from_object(instance)
       
   151     return data
       
   152 
       
   153 def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
       
   154     """
       
   155     Returns a ``SortedDict`` containing form fields for the given model.
       
   156 
       
   157     ``fields`` is an optional list of field names. If provided, only the named
       
   158     fields will be included in the returned fields.
       
   159 
       
   160     ``exclude`` is an optional list of field names. If provided, the named
       
   161     fields will be excluded from the returned fields, even if they are listed
       
   162     in the ``fields`` argument.
       
   163     """
       
   164     field_list = []
       
   165     ignored = []
       
   166     opts = model._meta
       
   167     for f in opts.fields + opts.many_to_many:
       
   168         if not f.editable:
       
   169             continue
       
   170         if fields and not f.name in fields:
       
   171             continue
       
   172         if exclude and f.name in exclude:
       
   173             continue
       
   174         if widgets and f.name in widgets:
       
   175             kwargs = {'widget': widgets[f.name]}
       
   176         else:
       
   177             kwargs = {}
       
   178         formfield = formfield_callback(f, **kwargs)
       
   179         if formfield:
       
   180             field_list.append((f.name, formfield))
       
   181         else:
       
   182             ignored.append(f.name)
       
   183     field_dict = SortedDict(field_list)
       
   184     if fields:
       
   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         )
       
   189     return field_dict
       
   190 
       
   191 class ModelFormOptions(object):
       
   192     def __init__(self, options=None):
       
   193         self.model = getattr(options, 'model', None)
       
   194         self.fields = getattr(options, 'fields', None)
       
   195         self.exclude = getattr(options, 'exclude', None)
       
   196         self.widgets = getattr(options, 'widgets', None)
       
   197 
       
   198 
       
   199 class ModelFormMetaclass(type):
       
   200     def __new__(cls, name, bases, attrs):
       
   201         formfield_callback = attrs.pop('formfield_callback',
       
   202                 lambda f, **kwargs: f.formfield(**kwargs))
       
   203         try:
       
   204             parents = [b for b in bases if issubclass(b, ModelForm)]
       
   205         except NameError:
       
   206             # We are defining ModelForm itself.
       
   207             parents = None
       
   208         declared_fields = get_declared_fields(bases, attrs, False)
       
   209         new_class = super(ModelFormMetaclass, cls).__new__(cls, name, bases,
       
   210                 attrs)
       
   211         if not parents:
       
   212             return new_class
       
   213 
       
   214         if 'media' not in attrs:
       
   215             new_class.media = media_property(new_class)
       
   216         opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))
       
   217         if opts.model:
       
   218             # If a model is defined, extract form fields from it.
       
   219             fields = fields_for_model(opts.model, opts.fields,
       
   220                                       opts.exclude, opts.widgets, formfield_callback)
       
   221             # Override default model fields with any custom declared ones
       
   222             # (plus, include all the other declared fields).
       
   223             fields.update(declared_fields)
       
   224         else:
       
   225             fields = declared_fields
       
   226         new_class.declared_fields = declared_fields
       
   227         new_class.base_fields = fields
       
   228         return new_class
       
   229 
       
   230 class BaseModelForm(BaseForm):
       
   231     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
       
   232                  initial=None, error_class=ErrorList, label_suffix=':',
       
   233                  empty_permitted=False, instance=None):
       
   234         opts = self._meta
       
   235         if instance is None:
       
   236             if opts.model is None:
       
   237                 raise ValueError('ModelForm has no model class specified.')
       
   238             # if we didn't get an instance, instantiate a new one
       
   239             self.instance = opts.model()
       
   240             object_data = {}
       
   241             self.instance._adding = True
       
   242         else:
       
   243             self.instance = instance
       
   244             self.instance._adding = False
       
   245             object_data = model_to_dict(instance, opts.fields, opts.exclude)
       
   246         # if initial was provided, it should override the values from instance
       
   247         if initial is not None:
       
   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
       
   253         super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
       
   254                                             error_class, label_suffix, empty_permitted)
       
   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 
       
   309     def clean(self):
       
   310         self._validate_unique = True
       
   311         return self.cleaned_data
       
   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 
       
   347     def validate_unique(self):
       
   348         """
       
   349         Calls the instance's validate_unique() method and updates the form's
       
   350         validation errors if any were raised.
       
   351         """
       
   352         exclude = self._get_validation_exclusions()
       
   353         try:
       
   354             self.instance.validate_unique(exclude=exclude)
       
   355         except ValidationError, e:
       
   356             self._update_errors(e.message_dict)
       
   357 
       
   358     def save(self, commit=True):
       
   359         """
       
   360         Saves this ``form``'s cleaned_data into model instance
       
   361         ``self.instance``.
       
   362 
       
   363         If commit=True, then the changes to ``instance`` will be saved to the
       
   364         database. Returns ``instance``.
       
   365         """
       
   366         if self.instance.pk is None:
       
   367             fail_message = 'created'
       
   368         else:
       
   369             fail_message = 'changed'
       
   370         return save_instance(self, self.instance, self._meta.fields,
       
   371                              fail_message, commit, construct=False)
       
   372 
       
   373     save.alters_data = True
       
   374 
       
   375 class ModelForm(BaseModelForm):
       
   376     __metaclass__ = ModelFormMetaclass
       
   377 
       
   378 def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
       
   379                        formfield_callback=lambda f: f.formfield()):
       
   380     # Create the inner Meta class. FIXME: ideally, we should be able to
       
   381     # construct a ModelForm without creating and passing in a temporary
       
   382     # inner class.
       
   383 
       
   384     # Build up a list of attributes that the Meta object will have.
       
   385     attrs = {'model': model}
       
   386     if fields is not None:
       
   387         attrs['fields'] = fields
       
   388     if exclude is not None:
       
   389         attrs['exclude'] = exclude
       
   390 
       
   391     # If parent form class already has an inner Meta, the Meta we're
       
   392     # creating needs to inherit from the parent's inner meta.
       
   393     parent = (object,)
       
   394     if hasattr(form, 'Meta'):
       
   395         parent = (form.Meta, object)
       
   396     Meta = type('Meta', parent, attrs)
       
   397 
       
   398     # Give this new form class a reasonable name.
       
   399     class_name = model.__name__ + 'Form'
       
   400 
       
   401     # Class attributes for the new form class.
       
   402     form_class_attrs = {
       
   403         'Meta': Meta,
       
   404         'formfield_callback': formfield_callback
       
   405     }
       
   406 
       
   407     return ModelFormMetaclass(class_name, (form,), form_class_attrs)
       
   408 
       
   409 
       
   410 # ModelFormSets ##############################################################
       
   411 
       
   412 class BaseModelFormSet(BaseFormSet):
       
   413     """
       
   414     A ``FormSet`` for editing a queryset and/or adding new objects to it.
       
   415     """
       
   416     model = None
       
   417 
       
   418     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
       
   419                  queryset=None, **kwargs):
       
   420         self.queryset = queryset
       
   421         defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
       
   422         defaults.update(kwargs)
       
   423         super(BaseModelFormSet, self).__init__(**defaults)
       
   424 
       
   425     def initial_form_count(self):
       
   426         """Returns the number of forms that are required in this FormSet."""
       
   427         if not (self.data or self.files):
       
   428             return len(self.get_queryset())
       
   429         return super(BaseModelFormSet, self).initial_form_count()
       
   430 
       
   431     def _existing_object(self, pk):
       
   432         if not hasattr(self, '_object_dict'):
       
   433             self._object_dict = dict([(o.pk, o) for o in self.get_queryset()])
       
   434         return self._object_dict.get(pk)
       
   435 
       
   436     def _construct_form(self, i, **kwargs):
       
   437         if self.is_bound and i < self.initial_form_count():
       
   438             pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
       
   439             pk = self.data[pk_key]
       
   440             pk_field = self.model._meta.pk
       
   441             pk = pk_field.get_db_prep_lookup('exact', pk,
       
   442                 connection=connections[self.get_queryset().db])
       
   443             if isinstance(pk, list):
       
   444                 pk = pk[0]
       
   445             kwargs['instance'] = self._existing_object(pk)
       
   446         if i < self.initial_form_count() and not kwargs.get('instance'):
       
   447             kwargs['instance'] = self.get_queryset()[i]
       
   448         return super(BaseModelFormSet, self)._construct_form(i, **kwargs)
       
   449 
       
   450     def get_queryset(self):
       
   451         if not hasattr(self, '_queryset'):
       
   452             if self.queryset is not None:
       
   453                 qs = self.queryset
       
   454             else:
       
   455                 qs = self.model._default_manager.get_query_set()
       
   456 
       
   457             # If the queryset isn't already ordered we need to add an
       
   458             # artificial ordering here to make sure that all formsets
       
   459             # constructed from this queryset have the same form order.
       
   460             if not qs.ordered:
       
   461                 qs = qs.order_by(self.model._meta.pk.name)
       
   462 
       
   463             # Removed queryset limiting here. As per discussion re: #13023
       
   464             # on django-dev, max_num should not prevent existing
       
   465             # related objects/inlines from being displayed.
       
   466             self._queryset = qs
       
   467         return self._queryset
       
   468 
       
   469     def save_new(self, form, commit=True):
       
   470         """Saves and returns a new model instance for the given form."""
       
   471         return form.save(commit=commit)
       
   472 
       
   473     def save_existing(self, form, instance, commit=True):
       
   474         """Saves and returns an existing model instance for the given form."""
       
   475         return form.save(commit=commit)
       
   476 
       
   477     def save(self, commit=True):
       
   478         """Saves model instances for every form, adding and changing instances
       
   479         as necessary, and returns the list of instances.
       
   480         """
       
   481         if not commit:
       
   482             self.saved_forms = []
       
   483             def save_m2m():
       
   484                 for form in self.saved_forms:
       
   485                     form.save_m2m()
       
   486             self.save_m2m = save_m2m
       
   487         return self.save_existing_objects(commit) + self.save_new_objects(commit)
       
   488 
       
   489     def clean(self):
       
   490         self.validate_unique()
       
   491 
       
   492     def validate_unique(self):
       
   493         # Collect unique_checks and date_checks to run from all the forms.
       
   494         all_unique_checks = set()
       
   495         all_date_checks = set()
       
   496         for form in self.forms:
       
   497             if not hasattr(form, 'cleaned_data'):
       
   498                 continue
       
   499             exclude = form._get_validation_exclusions()
       
   500             unique_checks, date_checks = form.instance._get_unique_checks(exclude=exclude)
       
   501             all_unique_checks = all_unique_checks.union(set(unique_checks))
       
   502             all_date_checks = all_date_checks.union(set(date_checks))
       
   503 
       
   504         errors = []
       
   505         # Do each of the unique checks (unique and unique_together)
       
   506         for uclass, unique_check in all_unique_checks:
       
   507             seen_data = set()
       
   508             for form in self.forms:
       
   509                 # if the form doesn't have cleaned_data then we ignore it,
       
   510                 # it's already invalid
       
   511                 if not hasattr(form, "cleaned_data"):
       
   512                     continue
       
   513                 # get each of the fields for which we have data on this form
       
   514                 if [f for f in unique_check if f in form.cleaned_data and form.cleaned_data[f] is not None]:
       
   515                     # get the data itself
       
   516                     row_data = tuple([form.cleaned_data[field] for field in unique_check])
       
   517                     # if we've aready seen it then we have a uniqueness failure
       
   518                     if row_data in seen_data:
       
   519                         # poke error messages into the right places and mark
       
   520                         # the form as invalid
       
   521                         errors.append(self.get_unique_error_message(unique_check))
       
   522                         form._errors[NON_FIELD_ERRORS] = self.get_form_error()
       
   523                         del form.cleaned_data
       
   524                         break
       
   525                     # mark the data as seen
       
   526                     seen_data.add(row_data)
       
   527         # iterate over each of the date checks now
       
   528         for date_check in all_date_checks:
       
   529             seen_data = set()
       
   530             uclass, lookup, field, unique_for = date_check
       
   531             for form in self.forms:
       
   532                 # if the form doesn't have cleaned_data then we ignore it,
       
   533                 # it's already invalid
       
   534                 if not hasattr(self, 'cleaned_data'):
       
   535                     continue
       
   536                 # see if we have data for both fields
       
   537                 if (form.cleaned_data and form.cleaned_data[field] is not None
       
   538                     and form.cleaned_data[unique_for] is not None):
       
   539                     # if it's a date lookup we need to get the data for all the fields
       
   540                     if lookup == 'date':
       
   541                         date = form.cleaned_data[unique_for]
       
   542                         date_data = (date.year, date.month, date.day)
       
   543                     # otherwise it's just the attribute on the date/datetime
       
   544                     # object
       
   545                     else:
       
   546                         date_data = (getattr(form.cleaned_data[unique_for], lookup),)
       
   547                     data = (form.cleaned_data[field],) + date_data
       
   548                     # if we've aready seen it then we have a uniqueness failure
       
   549                     if data in seen_data:
       
   550                         # poke error messages into the right places and mark
       
   551                         # the form as invalid
       
   552                         errors.append(self.get_date_error_message(date_check))
       
   553                         form._errors[NON_FIELD_ERRORS] = self.get_form_error()
       
   554                         del form.cleaned_data
       
   555                         break
       
   556                     seen_data.add(data)
       
   557         if errors:
       
   558             raise ValidationError(errors)
       
   559 
       
   560     def get_unique_error_message(self, unique_check):
       
   561         if len(unique_check) == 1:
       
   562             return ugettext("Please correct the duplicate data for %(field)s.") % {
       
   563                 "field": unique_check[0],
       
   564             }
       
   565         else:
       
   566             return ugettext("Please correct the duplicate data for %(field)s, "
       
   567                 "which must be unique.") % {
       
   568                     "field": get_text_list(unique_check, unicode(_("and"))),
       
   569                 }
       
   570 
       
   571     def get_date_error_message(self, date_check):
       
   572         return ugettext("Please correct the duplicate data for %(field_name)s "
       
   573             "which must be unique for the %(lookup)s in %(date_field)s.") % {
       
   574             'field_name': date_check[2],
       
   575             'date_field': date_check[3],
       
   576             'lookup': unicode(date_check[1]),
       
   577         }
       
   578 
       
   579     def get_form_error(self):
       
   580         return ugettext("Please correct the duplicate values below.")
       
   581 
       
   582     def save_existing_objects(self, commit=True):
       
   583         self.changed_objects = []
       
   584         self.deleted_objects = []
       
   585         if not self.get_queryset():
       
   586             return []
       
   587 
       
   588         saved_instances = []
       
   589         for form in self.initial_forms:
       
   590             pk_name = self._pk_field.name
       
   591             raw_pk_value = form._raw_value(pk_name)
       
   592 
       
   593             # clean() for different types of PK fields can sometimes return
       
   594             # the model instance, and sometimes the PK. Handle either.
       
   595             pk_value = form.fields[pk_name].clean(raw_pk_value)
       
   596             pk_value = getattr(pk_value, 'pk', pk_value)
       
   597 
       
   598             obj = self._existing_object(pk_value)
       
   599             if self.can_delete:
       
   600                 raw_delete_value = form._raw_value(DELETION_FIELD_NAME)
       
   601                 should_delete = form.fields[DELETION_FIELD_NAME].clean(raw_delete_value)
       
   602                 if should_delete:
       
   603                     self.deleted_objects.append(obj)
       
   604                     obj.delete()
       
   605                     continue
       
   606             if form.has_changed():
       
   607                 self.changed_objects.append((obj, form.changed_data))
       
   608                 saved_instances.append(self.save_existing(form, obj, commit=commit))
       
   609                 if not commit:
       
   610                     self.saved_forms.append(form)
       
   611         return saved_instances
       
   612 
       
   613     def save_new_objects(self, commit=True):
       
   614         self.new_objects = []
       
   615         for form in self.extra_forms:
       
   616             if not form.has_changed():
       
   617                 continue
       
   618             # If someone has marked an add form for deletion, don't save the
       
   619             # object.
       
   620             if self.can_delete:
       
   621                 raw_delete_value = form._raw_value(DELETION_FIELD_NAME)
       
   622                 should_delete = form.fields[DELETION_FIELD_NAME].clean(raw_delete_value)
       
   623                 if should_delete:
       
   624                     continue
       
   625             self.new_objects.append(self.save_new(form, commit=commit))
       
   626             if not commit:
       
   627                 self.saved_forms.append(form)
       
   628         return self.new_objects
       
   629 
       
   630     def add_fields(self, form, index):
       
   631         """Add a hidden field for the object's primary key."""
       
   632         from django.db.models import AutoField, OneToOneField, ForeignKey
       
   633         self._pk_field = pk = self.model._meta.pk
       
   634         # If a pk isn't editable, then it won't be on the form, so we need to
       
   635         # add it here so we can tell which object is which when we get the
       
   636         # data back. Generally, pk.editable should be false, but for some
       
   637         # reason, auto_created pk fields and AutoField's editable attribute is
       
   638         # True, so check for that as well.
       
   639         def pk_is_not_editable(pk):
       
   640             return ((not pk.editable) or (pk.auto_created or isinstance(pk, AutoField))
       
   641                 or (pk.rel and pk.rel.parent_link and pk_is_not_editable(pk.rel.to._meta.pk)))
       
   642         if pk_is_not_editable(pk) or pk.name not in form.fields:
       
   643             if form.is_bound:
       
   644                 pk_value = form.instance.pk
       
   645             else:
       
   646                 try:
       
   647                     if index is not None:
       
   648                         pk_value = self.get_queryset()[index].pk
       
   649                     else:
       
   650                         pk_value = None
       
   651                 except IndexError:
       
   652                     pk_value = None
       
   653             if isinstance(pk, OneToOneField) or isinstance(pk, ForeignKey):
       
   654                 qs = pk.rel.to._default_manager.get_query_set()
       
   655             else:
       
   656                 qs = self.model._default_manager.get_query_set()
       
   657             qs = qs.using(form.instance._state.db)
       
   658             form.fields[self._pk_field.name] = ModelChoiceField(qs, initial=pk_value, required=False, widget=HiddenInput)
       
   659         super(BaseModelFormSet, self).add_fields(form, index)
       
   660 
       
   661 def modelformset_factory(model, form=ModelForm, formfield_callback=lambda f: f.formfield(),
       
   662                          formset=BaseModelFormSet,
       
   663                          extra=1, can_delete=False, can_order=False,
       
   664                          max_num=None, fields=None, exclude=None):
       
   665     """
       
   666     Returns a FormSet class for the given Django model class.
       
   667     """
       
   668     form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
       
   669                              formfield_callback=formfield_callback)
       
   670     FormSet = formset_factory(form, formset, extra=extra, max_num=max_num,
       
   671                               can_order=can_order, can_delete=can_delete)
       
   672     FormSet.model = model
       
   673     return FormSet
       
   674 
       
   675 
       
   676 # InlineFormSets #############################################################
       
   677 
       
   678 class BaseInlineFormSet(BaseModelFormSet):
       
   679     """A formset for child objects related to a parent."""
       
   680     def __init__(self, data=None, files=None, instance=None,
       
   681                  save_as_new=False, prefix=None, queryset=None):
       
   682         from django.db.models.fields.related import RelatedObject
       
   683         if instance is None:
       
   684             self.instance = self.fk.rel.to()
       
   685         else:
       
   686             self.instance = instance
       
   687         self.save_as_new = save_as_new
       
   688         # is there a better way to get the object descriptor?
       
   689         self.rel_name = RelatedObject(self.fk.rel.to, self.model, self.fk).get_accessor_name()
       
   690         if self.fk.rel.field_name == self.fk.rel.to._meta.pk.name:
       
   691             backlink_value = self.instance
       
   692         else:
       
   693             backlink_value = getattr(self.instance, self.fk.rel.field_name)
       
   694         if queryset is None:
       
   695             queryset = self.model._default_manager
       
   696         qs = queryset.filter(**{self.fk.name: backlink_value})
       
   697         super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
       
   698                                                 queryset=qs)
       
   699 
       
   700     def initial_form_count(self):
       
   701         if self.save_as_new:
       
   702             return 0
       
   703         return super(BaseInlineFormSet, self).initial_form_count()
       
   704 
       
   705     def total_form_count(self):
       
   706         if self.save_as_new:
       
   707             return super(BaseInlineFormSet, self).initial_form_count()
       
   708         return super(BaseInlineFormSet, self).total_form_count()
       
   709 
       
   710     def _construct_form(self, i, **kwargs):
       
   711         form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs)
       
   712         if self.save_as_new:
       
   713             # Remove the primary key from the form's data, we are only
       
   714             # creating new instances
       
   715             form.data[form.add_prefix(self._pk_field.name)] = None
       
   716 
       
   717             # Remove the foreign key from the form's data
       
   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)
       
   722         return form
       
   723 
       
   724     #@classmethod
       
   725     def get_default_prefix(cls):
       
   726         from django.db.models.fields.related import RelatedObject
       
   727         return RelatedObject(cls.fk.rel.to, cls.model, cls.fk).get_accessor_name().replace('+','')
       
   728     get_default_prefix = classmethod(get_default_prefix)
       
   729 
       
   730     def save_new(self, form, commit=True):
       
   731         # Use commit=False so we can assign the parent key afterwards, then
       
   732         # save the object.
       
   733         obj = form.save(commit=False)
       
   734         pk_value = getattr(self.instance, self.fk.rel.field_name)
       
   735         setattr(obj, self.fk.get_attname(), getattr(pk_value, 'pk', pk_value))
       
   736         if commit:
       
   737             obj.save()
       
   738         # form.save_m2m() can be called via the formset later on if commit=False
       
   739         if commit and hasattr(form, 'save_m2m'):
       
   740             form.save_m2m()
       
   741         return obj
       
   742 
       
   743     def add_fields(self, form, index):
       
   744         super(BaseInlineFormSet, self).add_fields(form, index)
       
   745         if self._pk_field == self.fk:
       
   746             name = self._pk_field.name
       
   747             kwargs = {'pk_field': True}
       
   748         else:
       
   749             # The foreign key field might not be on the form, so we poke at the
       
   750             # Model field to get the label, since we need that for error messages.
       
   751             name = self.fk.name
       
   752             kwargs = {
       
   753                 'label': getattr(form.fields.get(name), 'label', capfirst(self.fk.verbose_name))
       
   754             }
       
   755             if self.fk.rel.field_name != self.fk.rel.to._meta.pk.name:
       
   756                 kwargs['to_field'] = self.fk.rel.field_name
       
   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)
       
   766 
       
   767     def get_unique_error_message(self, unique_check):
       
   768         unique_check = [field for field in unique_check if field != self.fk.name]
       
   769         return super(BaseInlineFormSet, self).get_unique_error_message(unique_check)
       
   770 
       
   771 
       
   772 def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
       
   773     """
       
   774     Finds and returns the ForeignKey from model to parent if there is one
       
   775     (returns None if can_fail is True and no such field exists). If fk_name is
       
   776     provided, assume it is the name of the ForeignKey field. Unles can_fail is
       
   777     True, an exception is raised if there is no ForeignKey from model to
       
   778     parent_model.
       
   779     """
       
   780     # avoid circular import
       
   781     from django.db.models import ForeignKey
       
   782     opts = model._meta
       
   783     if fk_name:
       
   784         fks_to_parent = [f for f in opts.fields if f.name == fk_name]
       
   785         if len(fks_to_parent) == 1:
       
   786             fk = fks_to_parent[0]
       
   787             if not isinstance(fk, ForeignKey) or \
       
   788                     (fk.rel.to != parent_model and
       
   789                      fk.rel.to not in parent_model._meta.get_parent_list()):
       
   790                 raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model))
       
   791         elif len(fks_to_parent) == 0:
       
   792             raise Exception("%s has no field named '%s'" % (model, fk_name))
       
   793     else:
       
   794         # Try to discover what the ForeignKey from model to parent_model is
       
   795         fks_to_parent = [
       
   796             f for f in opts.fields
       
   797             if isinstance(f, ForeignKey)
       
   798             and (f.rel.to == parent_model
       
   799                 or f.rel.to in parent_model._meta.get_parent_list())
       
   800         ]
       
   801         if len(fks_to_parent) == 1:
       
   802             fk = fks_to_parent[0]
       
   803         elif len(fks_to_parent) == 0:
       
   804             if can_fail:
       
   805                 return
       
   806             raise Exception("%s has no ForeignKey to %s" % (model, parent_model))
       
   807         else:
       
   808             raise Exception("%s has more than 1 ForeignKey to %s" % (model, parent_model))
       
   809     return fk
       
   810 
       
   811 
       
   812 def inlineformset_factory(parent_model, model, form=ModelForm,
       
   813                           formset=BaseInlineFormSet, fk_name=None,
       
   814                           fields=None, exclude=None,
       
   815                           extra=3, can_order=False, can_delete=True, max_num=None,
       
   816                           formfield_callback=lambda f: f.formfield()):
       
   817     """
       
   818     Returns an ``InlineFormSet`` for the given kwargs.
       
   819 
       
   820     You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey``
       
   821     to ``parent_model``.
       
   822     """
       
   823     fk = _get_foreign_key(parent_model, model, fk_name=fk_name)
       
   824     # enforce a max_num=1 when the foreign key to the parent model is unique.
       
   825     if fk.unique:
       
   826         max_num = 1
       
   827     kwargs = {
       
   828         'form': form,
       
   829         'formfield_callback': formfield_callback,
       
   830         'formset': formset,
       
   831         'extra': extra,
       
   832         'can_delete': can_delete,
       
   833         'can_order': can_order,
       
   834         'fields': fields,
       
   835         'exclude': exclude,
       
   836         'max_num': max_num,
       
   837     }
       
   838     FormSet = modelformset_factory(model, **kwargs)
       
   839     FormSet.fk = fk
       
   840     return FormSet
       
   841 
       
   842 
       
   843 # Fields #####################################################################
       
   844 
       
   845 class InlineForeignKeyHiddenInput(HiddenInput):
       
   846     def _has_changed(self, initial, data):
       
   847         return False
       
   848 
       
   849 class InlineForeignKeyField(Field):
       
   850     """
       
   851     A basic integer field that deals with validating the given value to a
       
   852     given parent instance in an inline.
       
   853     """
       
   854     default_error_messages = {
       
   855         'invalid_choice': _(u'The inline foreign key did not match the parent instance primary key.'),
       
   856     }
       
   857 
       
   858     def __init__(self, parent_instance, *args, **kwargs):
       
   859         self.parent_instance = parent_instance
       
   860         self.pk_field = kwargs.pop("pk_field", False)
       
   861         self.to_field = kwargs.pop("to_field", None)
       
   862         if self.parent_instance is not None:
       
   863             if self.to_field:
       
   864                 kwargs["initial"] = getattr(self.parent_instance, self.to_field)
       
   865             else:
       
   866                 kwargs["initial"] = self.parent_instance.pk
       
   867         kwargs["required"] = False
       
   868         kwargs["widget"] = InlineForeignKeyHiddenInput
       
   869         super(InlineForeignKeyField, self).__init__(*args, **kwargs)
       
   870 
       
   871     def clean(self, value):
       
   872         if value in EMPTY_VALUES:
       
   873             if self.pk_field:
       
   874                 return None
       
   875             # if there is no value act as we did before.
       
   876             return self.parent_instance
       
   877         # ensure the we compare the values as equal types.
       
   878         if self.to_field:
       
   879             orig = getattr(self.parent_instance, self.to_field)
       
   880         else:
       
   881             orig = self.parent_instance.pk
       
   882         if force_unicode(value) != force_unicode(orig):
       
   883             raise ValidationError(self.error_messages['invalid_choice'])
       
   884         return self.parent_instance
       
   885 
       
   886 class ModelChoiceIterator(object):
       
   887     def __init__(self, field):
       
   888         self.field = field
       
   889         self.queryset = field.queryset
       
   890 
       
   891     def __iter__(self):
       
   892         if self.field.empty_label is not None:
       
   893             yield (u"", self.field.empty_label)
       
   894         if self.field.cache_choices:
       
   895             if self.field.choice_cache is None:
       
   896                 self.field.choice_cache = [
       
   897                     self.choice(obj) for obj in self.queryset.all()
       
   898                 ]
       
   899             for choice in self.field.choice_cache:
       
   900                 yield choice
       
   901         else:
       
   902             for obj in self.queryset.all():
       
   903                 yield self.choice(obj)
       
   904 
       
   905     def __len__(self):
       
   906         return len(self.queryset)
       
   907 
       
   908     def choice(self, obj):
       
   909         if self.field.to_field_name:
       
   910             key = obj.serializable_value(self.field.to_field_name)
       
   911         else:
       
   912             key = obj.pk
       
   913         return (key, self.field.label_from_instance(obj))
       
   914 
       
   915 
       
   916 class ModelChoiceField(ChoiceField):
       
   917     """A ChoiceField whose choices are a model QuerySet."""
       
   918     # This class is a subclass of ChoiceField for purity, but it doesn't
       
   919     # actually use any of ChoiceField's implementation.
       
   920     default_error_messages = {
       
   921         'invalid_choice': _(u'Select a valid choice. That choice is not one of'
       
   922                             u' the available choices.'),
       
   923     }
       
   924 
       
   925     def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
       
   926                  required=True, widget=None, label=None, initial=None,
       
   927                  help_text=None, to_field_name=None, *args, **kwargs):
       
   928         if required and (initial is not None):
       
   929             self.empty_label = None
       
   930         else:
       
   931             self.empty_label = empty_label
       
   932         self.cache_choices = cache_choices
       
   933 
       
   934         # Call Field instead of ChoiceField __init__() because we don't need
       
   935         # ChoiceField.__init__().
       
   936         Field.__init__(self, required, widget, label, initial, help_text,
       
   937                        *args, **kwargs)
       
   938         self.queryset = queryset
       
   939         self.choice_cache = None
       
   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
       
   947 
       
   948     def _get_queryset(self):
       
   949         return self._queryset
       
   950 
       
   951     def _set_queryset(self, queryset):
       
   952         self._queryset = queryset
       
   953         self.widget.choices = self.choices
       
   954 
       
   955     queryset = property(_get_queryset, _set_queryset)
       
   956 
       
   957     # this method will be used to create object labels by the QuerySetIterator.
       
   958     # Override it to customize the label.
       
   959     def label_from_instance(self, obj):
       
   960         """
       
   961         This method is used to convert objects into strings; it's used to
       
   962         generate the labels for the choices presented by this object. Subclasses
       
   963         can override this method to customize the display of the choices.
       
   964         """
       
   965         return smart_unicode(obj)
       
   966 
       
   967     def _get_choices(self):
       
   968         # If self._choices is set, then somebody must have manually set
       
   969         # the property self.choices. In this case, just return self._choices.
       
   970         if hasattr(self, '_choices'):
       
   971             return self._choices
       
   972 
       
   973         # Otherwise, execute the QuerySet in self.queryset to determine the
       
   974         # choices dynamically. Return a fresh QuerySetIterator that has not been
       
   975         # consumed. Note that we're instantiating a new QuerySetIterator *each*
       
   976         # time _get_choices() is called (and, thus, each time self.choices is
       
   977         # accessed) so that we can ensure the QuerySet has not been consumed. This
       
   978         # construct might look complicated but it allows for lazy evaluation of
       
   979         # the queryset.
       
   980         return ModelChoiceIterator(self)
       
   981 
       
   982     choices = property(_get_choices, ChoiceField._set_choices)
       
   983 
       
   984     def to_python(self, value):
       
   985         if value in EMPTY_VALUES:
       
   986             return None
       
   987         try:
       
   988             key = self.to_field_name or 'pk'
       
   989             value = self.queryset.get(**{key: value})
       
   990         except self.queryset.model.DoesNotExist:
       
   991             raise ValidationError(self.error_messages['invalid_choice'])
       
   992         return value
       
   993 
       
   994     def validate(self, value):
       
   995         return Field.validate(self, value)
       
   996 
       
   997 class ModelMultipleChoiceField(ModelChoiceField):
       
   998     """A MultipleChoiceField whose choices are a model QuerySet."""
       
   999     widget = SelectMultiple
       
  1000     hidden_widget = MultipleHiddenInput
       
  1001     default_error_messages = {
       
  1002         'list': _(u'Enter a list of values.'),
       
  1003         'invalid_choice': _(u'Select a valid choice. %s is not one of the'
       
  1004                             u' available choices.'),
       
  1005         'invalid_pk_value': _(u'"%s" is not a valid value for a primary key.')
       
  1006     }
       
  1007 
       
  1008     def __init__(self, queryset, cache_choices=False, required=True,
       
  1009                  widget=None, label=None, initial=None,
       
  1010                  help_text=None, *args, **kwargs):
       
  1011         super(ModelMultipleChoiceField, self).__init__(queryset, None,
       
  1012             cache_choices, required, widget, label, initial, help_text,
       
  1013             *args, **kwargs)
       
  1014 
       
  1015     def clean(self, value):
       
  1016         if self.required and not value:
       
  1017             raise ValidationError(self.error_messages['required'])
       
  1018         elif not self.required and not value:
       
  1019             return []
       
  1020         if not isinstance(value, (list, tuple)):
       
  1021             raise ValidationError(self.error_messages['list'])
       
  1022         for pk in value:
       
  1023             try:
       
  1024                 self.queryset.filter(pk=pk)
       
  1025             except ValueError:
       
  1026                 raise ValidationError(self.error_messages['invalid_pk_value'] % pk)
       
  1027         qs = self.queryset.filter(pk__in=value)
       
  1028         pks = set([force_unicode(o.pk) for o in qs])
       
  1029         for val in value:
       
  1030             if force_unicode(val) not in pks:
       
  1031                 raise ValidationError(self.error_messages['invalid_choice'] % val)
       
  1032         return qs