Django

Code

Ticket #3297: quickie-file-uploads.diff

File quickie-file-uploads.diff, 6.2 kB (added by Andrew Sutherland <andrew@theptrgroup.com>, 2 years ago)

quick and dirty FileField? support that appears to work

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

    old new  
    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

    old new  
    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

    old new  
    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

    old new  
    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 = ''