Index: django/db/models/fields/__init__.py
===================================================================
--- django/db/models/fields/__init__.py (revision 4549)
+++ django/db/models/fields/__init__.py (working copy)
@@ -658,6 +658,10 @@
else:
func(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"])
+ def formfield_save_file(self, field_name, new_data, new_object):
+ func = getattr(new_object, 'save_%s_file' % self.name)
+ func(new_data[field_name][0]["filename"], new_data[field_name][0]["content"])
+
def get_directory_name(self):
return os.path.normpath(datetime.datetime.now().strftime(self.upload_to))
@@ -666,6 +670,11 @@
f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))
return os.path.normpath(f)
+ def formfield(self, **kwargs):
+ defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'widget': forms.FileInput}
+ defaults.update(kwargs)
+ return forms.FileField(**defaults)
+
class FilePathField(Field):
def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs):
self.path, self.match, self.recursive = path, match, recursive
Index: django/newforms/models.py
===================================================================
--- django/newforms/models.py (revision 4549)
+++ django/newforms/models.py (working copy)
@@ -16,6 +16,7 @@
This method is created for any form_for_model Form.
"""
+ from django.db import models
if self.errors:
raise ValueError("The %s could not be created because the data didn't validate." % self._model._meta.object_name)
return save_instance(self, self._model(), commit)
@@ -36,11 +37,16 @@
for f in opts.fields:
if not f.editable or isinstance(f, models.AutoField):
continue
+ if isinstance(f,models.FileField):
+ continue
setattr(instance, f.name, clean_data[f.name])
if commit:
instance.save()
for f in opts.many_to_many:
setattr(instance, f.attname, clean_data[f.name])
+ for f in opts.fields:
+ if isinstance(f, models.FileField):
+ f.formfield_save_file(f.name, clean_data, instance)
# GOTCHA: If many-to-many data is given and commit=False, the many-to-many
# data will be lost. This happens because a many-to-many options cannot be
# set on an object until after it's saved. Maybe we should raise an
Index: django/newforms/fields.py
===================================================================
--- django/newforms/fields.py (revision 4549)
+++ django/newforms/fields.py (working copy)
@@ -10,7 +10,7 @@
import time
__all__ = (
- 'Field', 'CharField', 'IntegerField',
+ 'Field', 'CharField', 'FileField', 'IntegerField',
'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
'DEFAULT_TIME_INPUT_FORMATS', 'TimeField',
'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
@@ -107,6 +107,21 @@
if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)):
return {'maxlength': str(self.max_length)}
+class FileField(Field):
+ def __init__(self,required=True,widget=None,label=None,initial=None):
+ super(FileField,self).__init__(required,widget,label,initial)
+
+ def clean(self, value):
+ super(FileField,self).clean(value)
+ if self.required:
+ if value[0]:
+ if not len(value[0]['content'])>0:
+ raise ValidationError(gettext(u'This field is required'))
+ else:
+ if not value[1]:
+ raise ValidationError(gettext(u'This field is required'))
+ return value
+
class IntegerField(Field):
def __init__(self, max_value=None, min_value=None, *args, **kwargs):
self.max_value, self.min_value = max_value, min_value
Index: django/newforms/widgets.py
===================================================================
--- django/newforms/widgets.py (revision 4549)
+++ django/newforms/widgets.py (working copy)
@@ -115,6 +115,24 @@
class FileInput(Input):
input_type = 'file'
+
+ def render(self,name,value,attrs=None,choices=()):
+ if value is None: value = ''
+ file_attrs = self.build_attrs(attrs, type='file', name=name+'_file')
+ final_attrs = self.build_attrs(attrs, type='hidden', name=name)
+ if value != '': final_attrs['value'] = smart_unicode(value) # only add the value attribute if a value is non-empty
+
+ if value != '':
+ currently = u'Currently: %s
Change: ' % smart_unicode(value)
+ current = u' ' % flatatt(final_attrs)
+ else:
+ currently = u''
+ current = u''
+
+ return u'%s%s' % (currently,flatatt(file_attrs),current)
+
+ def value_from_datadict(self,data,name):
+ return [data.get(name+'_file',None),data.get(name,None)]
class Textarea(Widget):
def render(self, name, value, attrs=None):
Index: tests/modeltests/model_forms/models.py
===================================================================
--- tests/modeltests/model_forms/models.py (revision 4549)
+++ tests/modeltests/model_forms/models.py (working copy)
@@ -54,6 +54,13 @@
def __str__(self):
return self.headline
+class File(models.Model):
+ description = models.CharField(maxlength=50)
+ file = models.FileField(upload_to='files')
+
+ def __str__(self):
+ return self.description
+
__test__ = {'API_TESTS': """
>>> from django.newforms import form_for_model, form_for_instance, save_instance, BaseForm, Form, CharField
>>> import datetime
@@ -370,4 +377,25 @@
Traceback (most recent call last):
...
ValidationError: [u'Select a valid choice. 5 is not one of the available choices.']
+
+Test for filefield
+
+>>> form_data = {'description': 'FileField test', 'file_file': {'content': 'FileField test', 'filename': 'filetest.txt'} }
+
+>>> TestFileForm = form_for_model(File)
+>>> empty_fileform = TestFileForm(auto_id=False)
+>>> print empty_fileform.as_ul()
+