Ticket #3297: quickie-file-uploads.diff

File quickie-file-uploads.diff, 6.2 KB (added by Andrew Sutherland <andrew@…>, 12 years ago)

quick and dirty FileField support that appears to work

  • django/db/models/fields/__init__.py

     
    660665        f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))
    661666        return os.path.normpath(f)
    662667
     668    def formfield(self, **kwargs):
     669        defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'widget':forms.FileInput}
     670        defaults.update(kwargs)
     671        return forms.FileField(**defaults)
     672
     673
    663674class FilePathField(Field):
    664675    def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs):
    665676        self.path, self.match, self.recursive = path, match, recursive
     
    710721    empty_strings_allowed = False
    711722    def get_manipulator_field_objs(self):
    712723        return [oldforms.IntegerField]
     724   
     725    def to_python(self, value):
     726        if value is None:
     727            return value
     728        try:
     729            return int(value)
     730        except (TypeError, ValueError):
     731            raise validators.ValidationError, gettext("This value must be an integer.")
    713732
    714733    def formfield(self, **kwargs):
    715734        defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name)}
  • django/newforms/models.py

     
    1318
    1419    This method is created for any form_for_model Form.
    1520    """
     21    from django.db import models
     22
    1623    if self.errors:
    1724        raise ValueError("The %s could not be created because the data didn't validate." % self._model._meta.object_name)
    18     obj = self._model(**self.clean_data)
     25    # The default initializer does not understand FileField data, we need to intercept.
     26    init_data = self.clean_data.copy()
     27    extra_data = {}
     28
     29    # Strip out data the model initializer can't handle, saving it in extra_data
     30    opts = self._model._meta
     31    for f in opts.fields:
     32        if isinstance(f, models.FileField):
     33            extra_data[f.name] = init_data.pop(f.name, [None, ''])
     34
     35    obj = self._model(**init_data)
     36
    1937    if commit:
    2038        obj.save()
     39
     40        # Now process that data we stripped out.
     41        # (We do this after the object is saved because we want to ensure the object
     42        # gets saved before we save the file.  Otherwise it could become orphaned.)
     43        for f in opts.fields:
     44            if isinstance(f, models.FileField):
     45                file_data, path_val_data = extra_data[f.name]
     46                # only save if there is a file
     47                if file_data is not None:
     48                   func = getattr(obj, 'save_%s_file' % f.name)
     49                   func(file_data['filename'], file_data['content'])
     50
    2151    return obj
    2252
    2353def save_instance(form, instance, commit=True):
     
    3666    for f in opts.fields + opts.many_to_many:
    3767        if isinstance(f, models.AutoField):
    3868            continue
    39         setattr(instance, f.attname, clean_data[f.name])
     69        # Skip FileFields, we don't want to process the upload yet, and that's
     70        #  the only way to change the value anyways.
     71        if isinstance(f, models.FileField) and commit:
     72            continue
     73        setattr(instance, f.name, clean_data[f.name])
    4074    if commit:
    4175        instance.save()
     76
     77        # Now save any uploaded files.
     78        for f in opts.fields:
     79          if isinstance(f, models.FileField):
     80                file_data = clean_data[f.name][0]
     81                # if there was an upload, save the file
     82                if file_data is not None:
     83                    func = getattr(instance, 'save_%s_file' % f.name)
     84                    func(file_data['filename'], file_data['content'])
     85                # otherwise we just want to leave the value intact...
     86                # (but if we did want to set it, it is in clean_data[f.name][1]
     87
    4288    return instance
    4389
    4490def make_instance_save(instance):
  • django/newforms/fields.py

     
    1010import time
    1111
    1212__all__ = (
    13     'Field', 'CharField', 'IntegerField',
     13    'Field', 'CharField', 'FileField', 'IntegerField',
    1414    'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
    1515    'DEFAULT_TIME_INPUT_FORMATS', 'TimeField',
    1616    'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
     
    105105        if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)):
    106106            return {'maxlength': str(self.max_length)}
    107107
     108class FileField(Field):
     109    def __init__(self, required=True, widget=None, label=None, initial=None):
     110        super(FileField, self).__init__(required, widget, label, initial)
     111
     112    def clean(self, value):
     113        super(FileField, self).clean(value)
     114        return value
     115
    108116class IntegerField(Field):
    109117    def __init__(self, max_value=None, min_value=None, required=True, widget=None, label=None, initial=None):
    110118        self.max_value, self.min_value = max_value, min_value
  • django/newforms/widgets.py

     
    108108class FileInput(Input):
    109109    input_type = 'file'
    110110
     111    def render(self, name, value, attrs=None, choices=()):
     112        if value is None: value = ''
     113        file_attrs = self.build_attrs(attrs, type='file', name=name+'_file')
     114        final_attrs = self.build_attrs(attrs, type='hidden', name=name)
     115        if value != '': final_attrs['value'] = smart_unicode(value) # Only add the 'value' attribute if a value is non-empty.
     116
     117        if value != '':
     118            currently = u'Currently: %s<br />Change: ' % smart_unicode(value)
     119        else:
     120            currently = u''
     121
     122        return u'%s<input %s /> <input%s />' % (currently, flatatt(file_attrs), flatatt(final_attrs))
     123
     124    def value_from_datadict(self, data, name):
     125        return [data.get(name+'_file', None), data.get(name, None)]
     126
     127
    111128class Textarea(Widget):
    112129    def render(self, name, value, attrs=None):
    113130        if value is None: value = ''
Back to Top