diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 3c58873..c2e5695 100644
a
|
b
|
class Field(object):
|
65 | 65 | 'blank': _(u'This field cannot be blank.'), |
66 | 66 | } |
67 | 67 | |
| 68 | defer_save = False # If true, defer saving until after other fields. |
| 69 | |
68 | 70 | # Generic field type description, usually overriden by subclasses |
69 | 71 | def _description(self): |
70 | 72 | return _(u'Field of type: %(field_type)s') % { |
diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py
index 6dfeddb..c592993 100644
a
|
b
|
class FileField(Field):
|
217 | 217 | # The descriptor to use for accessing the attribute off of the class. |
218 | 218 | descriptor_class = FileDescriptor |
219 | 219 | |
| 220 | defer_save = True |
| 221 | |
220 | 222 | description = ugettext_lazy("File path") |
221 | 223 | |
222 | 224 | def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs): |
diff --git a/django/forms/fields.py b/django/forms/fields.py
index de14a5c..7a1e55e 100644
a
|
b
|
class Field(object):
|
65 | 65 | 'required': _(u'This field is required.'), |
66 | 66 | 'invalid': _(u'Enter a valid value.'), |
67 | 67 | } |
| 68 | clean_takes_initial = False # If true, clean() takes initial value as well as data. |
68 | 69 | |
69 | 70 | # Tracks each time a Field instance is created. Used to retain order. |
70 | 71 | creation_counter = 0 |
… |
… |
class FileField(Field):
|
442 | 443 | 'max_length': _(u'Ensure this filename has at most %(max)d characters (it has %(length)d).'), |
443 | 444 | } |
444 | 445 | |
| 446 | clean_takes_initial = True |
| 447 | |
445 | 448 | def __init__(self, *args, **kwargs): |
446 | 449 | self.max_length = kwargs.pop('max_length', None) |
447 | 450 | super(FileField, self).__init__(*args, **kwargs) |
diff --git a/django/forms/forms.py b/django/forms/forms.py
index 7b2bc66..bcbe305 100644
a
|
b
|
class BaseForm(StrAndUnicode):
|
277 | 277 | # widgets split data over several HTML fields. |
278 | 278 | value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) |
279 | 279 | try: |
280 | | if isinstance(field, FileField): |
| 280 | if field.clean_takes_initial: |
281 | 281 | initial = self.initial.get(name, field.initial) |
282 | 282 | value = field.clean(value, initial) |
283 | 283 | else: |
diff --git a/django/forms/models.py b/django/forms/models.py
index cf465ad..c749cc4 100644
a
|
b
|
def construct_instance(form, instance, fields=None, exclude=None):
|
35 | 35 | opts = instance._meta |
36 | 36 | |
37 | 37 | cleaned_data = form.cleaned_data |
38 | | file_field_list = [] |
| 38 | deferred_list = [] |
39 | 39 | for f in opts.fields: |
40 | 40 | if not f.editable or isinstance(f, models.AutoField) \ |
41 | 41 | or not f.name in cleaned_data: |
… |
… |
def construct_instance(form, instance, fields=None, exclude=None):
|
46 | 46 | continue |
47 | 47 | # Defer saving file-type fields until after the other fields, so a |
48 | 48 | # callable upload_to can use the values from other fields. |
49 | | if isinstance(f, models.FileField): |
50 | | file_field_list.append(f) |
| 49 | if f.defer_save: |
| 50 | deferred_list.append(f) |
51 | 51 | else: |
52 | 52 | f.save_form_data(instance, cleaned_data[f.name]) |
53 | 53 | |
54 | | for f in file_field_list: |
| 54 | for f in deferred_list: |
55 | 55 | f.save_form_data(instance, cleaned_data[f.name]) |
56 | 56 | |
57 | 57 | return instance |