Skip to content

Commit

Permalink
Implemented maintenance actions as management commands
Browse files Browse the repository at this point in the history
  • Loading branch information
samluescher committed Jun 3, 2012
1 parent 245c0d4 commit fd55bd5
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 44 deletions.
1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -34,6 +34,7 @@ The Media Tree application
configuration
utils
bundled_extensions
management


Extending und using Media Tree with other applications
Expand Down
30 changes: 30 additions & 0 deletions docs/management.rst
@@ -0,0 +1,30 @@
Management Commands
*******************

You can use the following management commands to assist you with media file
management.


Orphaned files
==============

Use the following command to list all orphaned files, i.e. media files existing
in storage that are not in the database::

manage.py mediaorphaned

Use the following command to **delete** all orphaned files::

manage.py mediaorphaned --delete


Media cache
===========

Use the following command to list all media cache files, such as thumbnails::

manage.py mediacache

Use the following command to **delete** all media cache files::

manage.py mediacache --delete
67 changes: 23 additions & 44 deletions media_tree/admin/actions/maintenance_actions.py
@@ -1,9 +1,8 @@
from media_tree.utils.maintenance import get_broken_media, get_cache_files
from media_tree.utils import get_media_storage
from media_tree.media_backends import get_media_backend
from media_tree.models import FileNode
from media_tree.admin.actions.utils import get_actions_context
from media_tree.admin.actions.forms import DeleteOrphanedFilesForm, DeleteCacheFilesForm
from media_tree import settings as app_settings
from django import forms
from django.utils.translation import ungettext, ugettext as _
from django.template import RequestContext
Expand All @@ -13,43 +12,32 @@
from django.conf import settings
from django.contrib import messages
from django.utils.safestring import mark_safe
import os


def delete_orphaned_files(modeladmin, request, queryset=None):
from unicodedata import normalize
"""
Deletes orphaned files, i.e. media files existing in storage that are not in the database.
"""

execute = request.POST.get('execute')
media_subdir = app_settings.MEDIA_TREE_UPLOAD_SUBDIR

files_in_storage = []
storage = get_media_storage()
broken_node_links = []
orphaned_files_choices = []

files_in_db = []
nodes_with_missing_file_links = []
for node in FileNode.objects.filter(node_type=FileNode.FILE):
path = node.file.path
# need to normalize unicode path due to https://code.djangoproject.com/ticket/16315
path = normalize('NFC', path)
files_in_db.append(path)
if not storage.exists(node.file):
link = mark_safe('<a href="%s">%s</a>' % (node.get_admin_url(), node.__unicode__()))
nodes_with_missing_file_links.append(link)
broken_nodes, orphaned_files = get_broken_media()

files_in_storage = [storage.path(os.path.join(media_subdir, filename)) \
for filename in storage.listdir(media_subdir)[1]]
for node in broken_nodes:
link = mark_safe('<a href="%s">%s</a>' % (node.get_admin_url(), node.__unicode__()))
broken_node_links.append(link)

orphaned_files_choices = []
for file_path in files_in_storage:
# need to normalize unicode path due to https://code.djangoproject.com/ticket/16315
file_path = normalize('NFC', file_path)
if not file_path in files_in_db:
storage_name = os.path.join(media_subdir, os.path.basename(file_path))
link = mark_safe('<a href="%s">%s</a>' % (
storage.url(storage_name), file_path))
orphaned_files_choices.append((storage_name, link))

if not len(orphaned_files_choices) and not len(nodes_with_missing_file_links):
for storage_name in orphaned_files:
file_path = storage.path(storage_name)
link = mark_safe('<a href="%s">%s</a>' % (
storage.url(storage_name), file_path))
orphaned_files_choices.append((storage_name, link))

if not len(orphaned_files_choices) and not len(broken_node_links):
messages.success(request, message=_('There are no orphaned files.'))
return HttpResponseRedirect('')

Expand All @@ -76,7 +64,7 @@ def delete_orphaned_files(modeladmin, request, queryset=None):
'form': form,
'select_all': 'selected_files',
'node_list_title': _('The following files in the database do not exist in storage. You should fix these media objects:'),
'node_list': nodes_with_missing_file_links,
'node_list': broken_node_links,
})
return render_to_response('admin/media_tree/filenode/actions_form.html', c, context_instance=RequestContext(request))
delete_orphaned_files.short_description = _('Find orphaned files')
Expand All @@ -96,27 +84,18 @@ def rebuild_tree(modeladmin, request, queryset=None):

def clear_cache(modeladmin, request, queryset=None):
"""
Clears media cache files such as thumbnails.
"""
from unicodedata import normalize

execute = request.POST.get('execute')

files_in_storage = []
storage = get_media_storage()

cache_files_choices = []

for cache_dir in get_media_backend().get_cache_paths():
if storage.exists(cache_dir):
files_in_dir = [storage.path(os.path.join(cache_dir, filename)) \
for filename in storage.listdir(cache_dir)[1]]
for file_path in files_in_dir:
# need to normalize unicode path due to https://code.djangoproject.com/ticket/16315
file_path = normalize('NFC', file_path)
storage_name = os.path.join(cache_dir, os.path.basename(file_path))
link = mark_safe('<a href="%s">%s</a>' % (
storage.url(storage_name), storage_name))
cache_files_choices.append((storage_name, link))
for storage_name in get_cache_files():
link = mark_safe('<a href="%s">%s</a>' % (
storage.url(storage_name), storage_name))
cache_files_choices.append((storage_name, link))

if not len(cache_files_choices):
messages.warning(request, message=_('There are no cache files.'))
Expand Down
Empty file.
Empty file.
26 changes: 26 additions & 0 deletions media_tree/management/commands/mediacache.py
@@ -0,0 +1,26 @@
from media_tree.utils.maintenance import get_cache_files
from media_tree.utils import get_media_storage
from django.core.management.base import BaseCommand, CommandError
from optparse import make_option

class Command(BaseCommand):

help = 'Lists (and optionally deletes) all media_tree cache files.'

option_list = BaseCommand.option_list + (
make_option('--delete',
action='store_true',
dest='delete',
default=False,
help='Delete all cache files'),
)

def handle(self, *args, **options):
cache_files = get_cache_files()
storage = get_media_storage()
for path in cache_files:
if options['delete']:
storage.delete(path)
self.stdout.write("Deleted %s\n" % storage.path(path))
else:
self.stdout.write("%s\n" % storage.path(path))
27 changes: 27 additions & 0 deletions media_tree/management/commands/mediaorphaned.py
@@ -0,0 +1,27 @@
from media_tree.utils.maintenance import get_orphaned_files
from media_tree.utils import get_media_storage
from django.core.management.base import BaseCommand, CommandError
from optparse import make_option

class Command(BaseCommand):

help = 'Lists (and optionally deletes) all media_tree orphaned files, ' \
+ 'i.e. media files existing in storage that are not in the database.'

option_list = BaseCommand.option_list + (
make_option('--delete',
action='store_true',
dest='delete',
default=False,
help='Delete all orphaned files from storage'),
)

def handle(self, *args, **options):
orphaned_files = get_orphaned_files()
storage = get_media_storage()
for path in orphaned_files:
if options['delete']:
storage.delete(path)
self.stdout.write("Deleted %s\n" % storage.path(path))
else:
self.stdout.write("%s\n" % storage.path(path))
55 changes: 55 additions & 0 deletions media_tree/utils/maintenance.py
@@ -0,0 +1,55 @@
from media_tree.utils import get_media_storage
from media_tree.media_backends import get_media_backend
from media_tree.models import FileNode
from media_tree import settings as app_settings
from unicodedata import normalize
import os


def get_cache_files():
storage = get_media_storage()
cache_files = []

for cache_dir in get_media_backend().get_cache_paths():
if storage.exists(cache_dir):
files_in_dir = [storage.path(os.path.join(cache_dir, filename)) \
for filename in storage.listdir(cache_dir)[1]]
for file_path in files_in_dir:
# need to normalize unicode path due to https://code.djangoproject.com/ticket/16315
file_path = normalize('NFC', file_path)
storage_name = os.path.join(cache_dir, os.path.basename(file_path))
cache_files.append(storage_name)

return cache_files


def get_broken_media():
storage = get_media_storage()
media_subdir = app_settings.MEDIA_TREE_UPLOAD_SUBDIR
broken_nodes = []
orphaned_files = []

files_in_db = []
for node in FileNode.objects.filter(node_type=FileNode.FILE):
path = node.file.path
# need to normalize unicode path due to https://code.djangoproject.com/ticket/16315
path = normalize('NFC', path)
files_in_db.append(path)
if not storage.exists(node.file):
broken_nodes.append(node)

files_in_storage = [storage.path(os.path.join(media_subdir, filename)) \
for filename in storage.listdir(media_subdir)[1]]

for file_path in files_in_storage:
# need to normalize unicode path due to https://code.djangoproject.com/ticket/16315
file_path = normalize('NFC', file_path)
if not file_path in files_in_db:
storage_name = os.path.join(media_subdir, os.path.basename(file_path))
orphaned_files.append(storage_name)

return [broken_nodes, orphaned_files]


def get_orphaned_files():
return get_broken_media()[1]

0 comments on commit fd55bd5

Please sign in to comment.