Commit 1581befa authored by chrisspen's avatar chrisspen
Browse files

Added management command to handle bulk file deletions.

parent 487c1697
......@@ -47,6 +47,13 @@ system, run:
$ python manage.py database_files_dump
Note, that when a field referencing a file is cleared, the corresponding file
in the database and on the file system will not be automatically deleted.
To delete all files in the database and file system not referenced by any model
fields, run:
$ python manage.py database_files_cleanup
Test suite
----------
......
import os
from django.conf import settings
from django.core.files.storage import default_storage
from django.core.management.base import BaseCommand, CommandError
from django.db.models import FileField, ImageField, get_models
from database_files.models import File
class Command(BaseCommand):
args = ''
help = 'Deletes all files in the database that are not referenced by ' + \
'any model fields.'
def handle(self, *args, **options):
tmp_debug = settings.DEBUG
settings.DEBUG = False
names = set()
try:
for model in get_models():
for field in model._meta.fields:
if not isinstance(field, (FileField, ImageField)):
continue
# Ignore records with null or empty string values.
q = {'%s__isnull'%field.name:False}
xq = {field.name:''}
for row in model.objects.filter(**q).exclude(**xq):
file = getattr(row, field.name)
if file is None:
continue
if not file.name:
continue
names.add(file.name)
# Find all database files with names not in our list.
orphan_files = File.objects.exclude(name__in=names)
for f in orphan_files:
print 'Deleting %s...' % (f.name,)
default_storage.delete(f.name)
finally:
settings.DEBUG = tmp_debug
......@@ -6,6 +6,7 @@ from django.core.management.base import BaseCommand, CommandError
from django.db.models import FileField, ImageField
from database_files.models import File
from database_files.utils import write_file
from optparse import make_option
......@@ -29,14 +30,10 @@ class Command(BaseCommand):
for file in q:
i += 1
print '%i of %i' % (i, total)
fqfn = os.path.join(settings.MEDIA_ROOT, file.name)
fqfn = os.path.normpath(fqfn)
if os.path.isfile(fqfn) and not options['overwrite']:
continue
dirs,fn = os.path.split(fqfn)
if not os.path.isdir(dirs):
os.makedirs(dirs)
open(fqfn, 'wb').write(file.content)
write_file(
file.name,
file.content.read(),
options['overwrite'])
finally:
settings.DEBUG = tmp_debug
\ No newline at end of file
......@@ -5,8 +5,6 @@ from django.core.files.storage import default_storage
from django.core.management.base import BaseCommand, CommandError
from django.db.models import FileField, ImageField, get_models
from optparse import make_option
class Command(BaseCommand):
args = ''
help = 'Loads all files on the filesystem referenced by FileFields ' + \
......
......@@ -7,6 +7,7 @@ from django.core.files.storage import FileSystemStorage
from django.core.urlresolvers import reverse
from database_files import models
from database_files.utils import write_file
class DatabaseStorage(FileSystemStorage):
......@@ -57,11 +58,16 @@ class DatabaseStorage(FileSystemStorage):
size = content.size
except AttributeError:
size = os.path.getsize(full_path)
content = content.read()
f = models.File.objects.create(
content=content.read(),
content=content,
size=size,
name=name,
)
# Automatically write the change to the local file system.
if getattr(settings, 'DATABASE_FILES_FS_AUTO_WRITE', True):
write_file(name, content, overwrite=True)
#TODO:add callback to handle custom save behavior?
return self._generate_name(name, f.pk)
def exists(self, name):
......@@ -77,7 +83,6 @@ class DatabaseStorage(FileSystemStorage):
"""
Deletes the file with filename `name` from the database and filesystem.
"""
full_path = self.path(name)
try:
models.File.objects.get_from_name(name).delete()
except models.File.DoesNotExist:
......
import os
from django.conf import settings
def write_file(name, content, overwrite=False):
"""
Writes the given content to the relative filename under the MEDIA_ROOT.
"""
fqfn = os.path.join(settings.MEDIA_ROOT, name)
fqfn = os.path.normpath(fqfn)
if os.path.isfile(fqfn) and not overwrite:
return
dirs,fn = os.path.split(fqfn)
if not os.path.isdir(dirs):
os.makedirs(dirs)
open(fqfn, 'wb').write(content)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment