Ticket #2413: inline_files_bug.diff

File inline_files_bug.diff, 5.9 KB (added by Joel Heenan <joelh-django@…>, 18 years ago)

bug fix for ticket 2413

  • django/db/models/manipulators.py

     
    169169                    for f in related.opts.fields:
    170170                        if f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) in (None, ''):
    171171                            all_cores_given = False
     172                        # if the new file is blank and the old file is blank
     173                        if f.core and isinstance(f,FileField) and f.get_manipulator_new_file_data(rel_new_data, rel=True) in (None, '') and \
     174                                                                  f.get_manipulator_new_data(rel_new_data, rel=True) in (None,''):
     175                            all_cores_given = False
    172176                        elif f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) not in (None, ''):
    173177                            all_cores_blank = False
    174178                        # If this field isn't editable, give it the same value it had
     
    200204                        # Save any uploaded files.
    201205                        for f in related.opts.fields:
    202206                            if child_follow.get(f.name, None):
    203                                 if isinstance(f, FileField) and rel_new_data.get(f.name, False):
     207                                if isinstance(f, FileField):
    204208                                    f.save_file(rel_new_data, new_rel_obj, self.change and old_rel_obj or None, old_rel_obj is not None, rel=True)
    205209
    206210                        # Calculate whether any fields have changed.
     
    221225
    222226                    # If, in the change stage, all of the core fields were blank and
    223227                    # the primary key (ID) was provided, delete the item.
    224                     if self.change and all_cores_blank and old_rel_obj:
     228                    elif self.change and all_cores_blank and old_rel_obj:
    225229                        new_rel_obj.delete()
    226230                        self.fields_deleted.append('%s "%s"' % (related.opts.verbose_name, old_rel_obj))
    227231
  • django/db/models/fields/__init__.py

     
    271271    def get_validator_unique_lookup_type(self):
    272272        return '%s__exact' % self.name
    273273
     274    def get_manipulator_new_file_data(self, new_data, rel=False):
     275        """
     276        Return the file data in order to overcome some nasty
     277        corner cases
     278        """
     279        if rel:
     280            val = new_data.get(self.name+"_file", [self.get_default()])
     281            try:
     282                return val[0]
     283            except(IndexError):
     284                return self.get_default()
     285        val = new_data.get(self.name+"_file",self.get_default())
     286        if not self.empty_strings_allowed and val == '' and self.null:
     287            val = None
     288        return val
     289
    274290    def get_manipulator_new_data(self, new_data, rel=False):
    275291        """
    276292        Given the full new_data dictionary (from the manipulator), returns this
  • tests/modeltests/inline_files/models.py

     
     1"""
     2This tests an inline file in an object when saved via a dict
     3(normally called through HTML say in the admin interface) will
     4not delete the file. This comes about because to the manipulator
     5there is confusion about whether you have ignored a file or want
     6to delete it.
     7
     8Also note that while its not primarily designed to do so it tests
     9a number of other things in the code. It tests the case of an
     10object that has only a file field and a foreign key - this is
     11a particularly nasty case because the file is the only core field
     12yet its always unclear whether it has been submitted (because people
     13don't resubmit entire files).
     14
     15Author: Joel Heenan
     16"""
     17
     18from django.db import models
     19
     20class Foo(models.Model):
     21    name = models.CharField(maxlength=200)
     22    class Admin:
     23        pass
     24
     25class FooFiles(models.Model):
     26    file = models.FileField(verbose_name="The File",core=True,upload_to='foo/')
     27    foo = models.ForeignKey(Foo,edit_inline=models.TABULAR)
     28    class Admin:
     29        pass
     30    def __str__(self):
     31        return self.file
     32
     33API_TESTS = """
     34>>> from django.db import models
     35
     36# lets submit something that looks like a normal submit
     37# with a bunch of empty files and one filled in with some content
     38>>> dict = {'foofiles.1.id': [''], 'foofiles.0.id': [''], 'foofiles.2.id': [''], 'foofiles.1.file': [''], 'foofiles.2.file': [''], 'foofiles.0.file': [''], 'foofiles.0.file_file': [{'content': 'FILE CONTENT GOES HERE', 'content-type': 'text/x-patch', 'filename': 'test_file'}], 'name': 'testfoo3'}
     39
     40>>> manipulator = Foo.AddManipulator()
     41
     42>>> f = manipulator.save(dict)
     43
     44# as we expect our file is there
     45>>> print f.foofiles_set.filter()[0]
     46foo/test_file
     47
     48# previous versions of the code would create empty file records
     49>>> print f.foofiles_set.count()
     501
     51
     52# ok lets resubmit to the change manipulator. note we must
     53# re-use the objects id
     54>>> dict = {'foofiles.1.id': [''], 'foofiles.0.id': [f.foofiles_set.filter()[0].id], 'foofiles.2.id': [''], 'foofiles.1.file': [''], 'foofiles.2.file': [''], 'foofiles.0.file': ['test_file'], 'name': 'testfoo3'}
     55
     56>>> manipulator = Foo.ChangeManipulator(f.id)
     57
     58>>> f = manipulator.save(dict)
     59
     60# yay or file still exists. previous versions of the code would delete it
     61>>> print f.foofiles_set.filter()[0]
     62foo/test_file
     63
     64# no blank files added
     65>>> print f.foofiles_set.count()
     661
     67
     68# cleanup
     69>>> f.delete()
     70>>>
     71"""
Back to Top