bgneal@668: """avatar_cleanup - a management command to remove orphaned avatar files.""" bgneal@668: bgneal@668: from optparse import make_option bgneal@668: import os bgneal@668: bgneal@668: from django.core.management.base import NoArgsCommand bgneal@668: from django.conf import settings bgneal@668: bgneal@668: from bio.models import UserProfile bgneal@668: bgneal@668: bgneal@668: class Command(NoArgsCommand): bgneal@668: help = "Finds and optionally deletes orphan avatar files" bgneal@668: option_list = NoArgsCommand.option_list + ( bgneal@668: make_option('--delete', bgneal@668: action='store_true', bgneal@668: dest='delete', bgneal@668: default=False, bgneal@668: help='Delete orphan files'), bgneal@668: ) bgneal@668: bgneal@668: def handle_noargs(self, **options): bgneal@668: """Find and optionally delete orphan avatar files.""" bgneal@668: bgneal@668: delete = options.get('delete', False) bgneal@668: bgneal@668: orphans = set() bgneal@668: missing = [] bgneal@668: bgneal@668: avatar_dir = os.path.join(settings.MEDIA_ROOT, settings.AVATAR_DIR) bgneal@668: default_avatar = os.path.join(avatar_dir, bgneal@668: settings.AVATAR_DEFAULT_URL.split('/')[-1]) bgneal@668: bgneal@668: # find the set of all files in the downloads area bgneal@668: for root, dirs, files in os.walk(avatar_dir, followlinks=True): bgneal@668: for name in files: bgneal@668: orphans.add(unicode(os.path.join(root, name), 'utf-8')) bgneal@668: bgneal@668: try: bgneal@668: orphans.remove(default_avatar) bgneal@668: except KeyError: bgneal@668: self.stderr.write("Default avatar file missing! - {}\n".format( bgneal@668: default_avatar)) bgneal@668: bgneal@668: # examine the UserProfile objects bgneal@668: for profile in UserProfile.objects.iterator(): bgneal@668: if profile.avatar: bgneal@668: try: bgneal@668: orphans.remove(profile.avatar.path) bgneal@668: except KeyError: bgneal@668: missing.append(profile) bgneal@668: bgneal@668: if orphans and delete: bgneal@668: for path in orphans: bgneal@668: self.stdout.write("Deleting: {}\n".format(path)) bgneal@668: os.remove(path) bgneal@668: elif orphans: bgneal@668: self.stdout.write("Orphan files:\n") bgneal@668: for orphan in orphans: bgneal@668: self.stdout.write("{}\n".format(orphan)) bgneal@668: bgneal@668: if missing: bgneal@668: self.stdout.write("Users with missing avatar files:\n") bgneal@668: for profile in missing: bgneal@668: self.stdout.write("{}\n".format(profile.user.username)) bgneal@668: bgneal@668: empty_dirs = [] bgneal@668: # check for empty directories after deletions bgneal@668: for root, dirs, files in os.walk(avatar_dir, followlinks=True): bgneal@668: if not len(dirs) and not len(files): bgneal@668: empty_dirs.append(root) bgneal@668: bgneal@668: if empty_dirs and delete: bgneal@668: for path in empty_dirs: bgneal@668: self.stdout.write("Deleting empty dir: {}\n".format(path)) bgneal@668: os.removedirs(path) bgneal@668: elif empty_dirs: bgneal@668: self.stdout.write("Empty directories:\n") bgneal@668: for d in empty_dirs: bgneal@668: self.stdout.write("{}\n".format(d))