mirror of
https://github.com/django/django.git
synced 2025-07-05 02:09:13 +00:00
[1.2.X] Fixed #6456 - Excised FileField file deletion to avoid data loss. Thanks to durdinator for the report.
Backport of r15321 from trunk. Backported despite slight backwards-incompatibility due to potential for data loss. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15322 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
c4b0878b43
commit
3af1bf8217
@ -258,19 +258,6 @@ class FileField(Field):
|
|||||||
def contribute_to_class(self, cls, name):
|
def contribute_to_class(self, cls, name):
|
||||||
super(FileField, self).contribute_to_class(cls, name)
|
super(FileField, self).contribute_to_class(cls, name)
|
||||||
setattr(cls, self.name, self.descriptor_class(self))
|
setattr(cls, self.name, self.descriptor_class(self))
|
||||||
signals.post_delete.connect(self.delete_file, sender=cls)
|
|
||||||
|
|
||||||
def delete_file(self, instance, sender, **kwargs):
|
|
||||||
file = getattr(instance, self.attname)
|
|
||||||
# If no other object of this type references the file,
|
|
||||||
# and it's not the default value for future objects,
|
|
||||||
# delete it from the backend.
|
|
||||||
if file and file.name != self.default and \
|
|
||||||
not sender._default_manager.filter(**{self.name: file.name}):
|
|
||||||
file.delete(save=False)
|
|
||||||
elif file:
|
|
||||||
# Otherwise, just close the file, so it doesn't tie up resources.
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
def get_directory_name(self):
|
def get_directory_name(self):
|
||||||
return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to))))
|
return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to))))
|
||||||
|
@ -7,7 +7,7 @@ Welcome to Django 1.2.5!
|
|||||||
This is the fifth "bugfix" release in the Django 1.2 series,
|
This is the fifth "bugfix" release in the Django 1.2 series,
|
||||||
improving the stability and performance of the Django 1.2 codebase.
|
improving the stability and performance of the Django 1.2 codebase.
|
||||||
|
|
||||||
With one exception, Django 1.2.5 maintains backwards compatibility
|
With two exceptions, Django 1.2.5 maintains backwards compatibility
|
||||||
with Django 1.2.4, but contain a number of fixes and other
|
with Django 1.2.4, but contain a number of fixes and other
|
||||||
improvements. Django 1.2.5 is a recommended upgrade for any
|
improvements. Django 1.2.5 is a recommended upgrade for any
|
||||||
development or deployment currently using or targeting Django 1.2.
|
development or deployment currently using or targeting Django 1.2.
|
||||||
@ -15,8 +15,25 @@ development or deployment currently using or targeting Django 1.2.
|
|||||||
For full details on the new features, backwards incompatibilities, and
|
For full details on the new features, backwards incompatibilities, and
|
||||||
deprecated features in the 1.2 branch, see the :doc:`/releases/1.2`.
|
deprecated features in the 1.2 branch, see the :doc:`/releases/1.2`.
|
||||||
|
|
||||||
One backwards incompatibility
|
Backwards incompatible changes
|
||||||
=============================
|
==============================
|
||||||
|
|
||||||
|
FileField no longer deletes files
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
In earlier Django versions, when a model instance containing a
|
||||||
|
:class:`~django.db.models.FileField` was deleted,
|
||||||
|
:class:`~django.db.models.FileField` took it upon itself to also delete the
|
||||||
|
file from the backend storage. This opened the door to several potentially
|
||||||
|
serious data-loss scenarios, including rolled-back transactions and fields on
|
||||||
|
different models referencing the same file. In Django 1.2.5,
|
||||||
|
:class:`~django.db.models.FileField` will never delete files from the backend
|
||||||
|
storage. If you need cleanup of orphaned files, you'll need to handle it
|
||||||
|
yourself (for instance, with a custom management command that can be run
|
||||||
|
manually or scheduled to run periodically via e.g. cron).
|
||||||
|
|
||||||
|
Use of custom SQL to load initial data in tests
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Django provides a custom SQL hooks as a way to inject hand-crafted SQL
|
Django provides a custom SQL hooks as a way to inject hand-crafted SQL
|
||||||
into the database synchronization process. One of the possible uses
|
into the database synchronization process. One of the possible uses
|
||||||
|
@ -58,11 +58,10 @@ class FileTests(TestCase):
|
|||||||
cache.set("obj2", obj2)
|
cache.set("obj2", obj2)
|
||||||
self.assertEqual(cache.get("obj2").normal.name, "tests/django_test_1.txt")
|
self.assertEqual(cache.get("obj2").normal.name, "tests/django_test_1.txt")
|
||||||
|
|
||||||
# Deleting an object deletes the file it uses, if there are no other
|
# Deleting an object does not delete the file it uses.
|
||||||
# objects still using that file.
|
|
||||||
obj2.delete()
|
obj2.delete()
|
||||||
obj2.normal.save("django_test.txt", ContentFile("more content"))
|
obj2.normal.save("django_test.txt", ContentFile("more content"))
|
||||||
self.assertEqual(obj2.normal.name, "tests/django_test_1.txt")
|
self.assertEqual(obj2.normal.name, "tests/django_test_2.txt")
|
||||||
|
|
||||||
# Multiple files with the same name get _N appended to them.
|
# Multiple files with the same name get _N appended to them.
|
||||||
objs = [Storage() for i in range(3)]
|
objs = [Storage() for i in range(3)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user