bgneal@668
|
1 """avatar_cleanup - a management command to remove orphaned avatar files."""
|
bgneal@668
|
2
|
bgneal@668
|
3 from optparse import make_option
|
bgneal@668
|
4 import os
|
bgneal@668
|
5
|
bgneal@668
|
6 from django.core.management.base import NoArgsCommand
|
bgneal@668
|
7 from django.conf import settings
|
bgneal@668
|
8
|
bgneal@668
|
9 from bio.models import UserProfile
|
bgneal@668
|
10
|
bgneal@668
|
11
|
bgneal@668
|
12 class Command(NoArgsCommand):
|
bgneal@668
|
13 help = "Finds and optionally deletes orphan avatar files"
|
bgneal@668
|
14 option_list = NoArgsCommand.option_list + (
|
bgneal@668
|
15 make_option('--delete',
|
bgneal@668
|
16 action='store_true',
|
bgneal@668
|
17 dest='delete',
|
bgneal@668
|
18 default=False,
|
bgneal@668
|
19 help='Delete orphan files'),
|
bgneal@668
|
20 )
|
bgneal@668
|
21
|
bgneal@668
|
22 def handle_noargs(self, **options):
|
bgneal@668
|
23 """Find and optionally delete orphan avatar files."""
|
bgneal@668
|
24
|
bgneal@668
|
25 delete = options.get('delete', False)
|
bgneal@668
|
26
|
bgneal@668
|
27 orphans = set()
|
bgneal@668
|
28 missing = []
|
bgneal@668
|
29
|
bgneal@668
|
30 avatar_dir = os.path.join(settings.MEDIA_ROOT, settings.AVATAR_DIR)
|
bgneal@668
|
31 default_avatar = os.path.join(avatar_dir,
|
bgneal@668
|
32 settings.AVATAR_DEFAULT_URL.split('/')[-1])
|
bgneal@668
|
33
|
bgneal@668
|
34 # find the set of all files in the downloads area
|
bgneal@668
|
35 for root, dirs, files in os.walk(avatar_dir, followlinks=True):
|
bgneal@668
|
36 for name in files:
|
bgneal@668
|
37 orphans.add(unicode(os.path.join(root, name), 'utf-8'))
|
bgneal@668
|
38
|
bgneal@668
|
39 try:
|
bgneal@668
|
40 orphans.remove(default_avatar)
|
bgneal@668
|
41 except KeyError:
|
bgneal@668
|
42 self.stderr.write("Default avatar file missing! - {}\n".format(
|
bgneal@668
|
43 default_avatar))
|
bgneal@668
|
44
|
bgneal@668
|
45 # examine the UserProfile objects
|
bgneal@668
|
46 for profile in UserProfile.objects.iterator():
|
bgneal@668
|
47 if profile.avatar:
|
bgneal@668
|
48 try:
|
bgneal@668
|
49 orphans.remove(profile.avatar.path)
|
bgneal@668
|
50 except KeyError:
|
bgneal@668
|
51 missing.append(profile)
|
bgneal@668
|
52
|
bgneal@668
|
53 if orphans and delete:
|
bgneal@668
|
54 for path in orphans:
|
bgneal@668
|
55 self.stdout.write("Deleting: {}\n".format(path))
|
bgneal@668
|
56 os.remove(path)
|
bgneal@668
|
57 elif orphans:
|
bgneal@668
|
58 self.stdout.write("Orphan files:\n")
|
bgneal@668
|
59 for orphan in orphans:
|
bgneal@668
|
60 self.stdout.write("{}\n".format(orphan))
|
bgneal@668
|
61
|
bgneal@668
|
62 if missing:
|
bgneal@668
|
63 self.stdout.write("Users with missing avatar files:\n")
|
bgneal@668
|
64 for profile in missing:
|
bgneal@668
|
65 self.stdout.write("{}\n".format(profile.user.username))
|
bgneal@668
|
66
|
bgneal@668
|
67 empty_dirs = []
|
bgneal@668
|
68 # check for empty directories after deletions
|
bgneal@668
|
69 for root, dirs, files in os.walk(avatar_dir, followlinks=True):
|
bgneal@668
|
70 if not len(dirs) and not len(files):
|
bgneal@668
|
71 empty_dirs.append(root)
|
bgneal@668
|
72
|
bgneal@668
|
73 if empty_dirs and delete:
|
bgneal@668
|
74 for path in empty_dirs:
|
bgneal@668
|
75 self.stdout.write("Deleting empty dir: {}\n".format(path))
|
bgneal@668
|
76 os.removedirs(path)
|
bgneal@668
|
77 elif empty_dirs:
|
bgneal@668
|
78 self.stdout.write("Empty directories:\n")
|
bgneal@668
|
79 for d in empty_dirs:
|
bgneal@668
|
80 self.stdout.write("{}\n".format(d))
|