diff --git a/avatar/conf.py b/avatar/conf.py index 0379945..9a694d3 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -17,6 +17,7 @@ class AvatarConf(AppConf): MAX_SIZE = 1024 * 1024 THUMB_FORMAT = 'JPEG' THUMB_QUALITY = 85 + USERID_AS_USERDIRNAME = False HASH_FILENAMES = False HASH_USERDIRNAMES = False ALLOWED_FILE_EXTS = None diff --git a/avatar/management/commands/migrate_avatars.py b/avatar/management/commands/migrate_avatars.py new file mode 100644 index 0000000..25bd1cc --- /dev/null +++ b/avatar/management/commands/migrate_avatars.py @@ -0,0 +1,54 @@ +import os +import shutil +from django.core.management import call_command +from django.core.management.base import NoArgsCommand +from avatar.conf import settings +from avatar.models import Avatar, avatar_file_path +from django.core.files import File + + +class Command(NoArgsCommand): + help = ("Check if avatar userdirname folder correspond " + "with actual userdirname pattern " + "affect with options like AVATAR_USERID_AS_USERDIRNAME " + "or AVATAR_HASH_USERDIRNAMES.") + + def handle_noargs(self, **options): + # define path to avatar folders + avatar_path = os.path.join(settings.MEDIA_URL, + settings.AVATAR_STORAGE_DIR) + + have_change = False + for avatar in Avatar.objects.all(): + # get actuel path of avatar + new_path = os.path.join(settings.MEDIA_URL, + avatar_file_path(avatar)) + original_path = avatar.avatar.url + if new_path != original_path: + print("Move Avatar id=%s from %s to %s." % (avatar.id, + original_path, + new_path)) + + # if different path: we copy + generate new thumbnails + clean + media_path = original_path.replace(settings.MEDIA_URL, "") + media_path = os.path.join(settings.MEDIA_ROOT, media_path) + # copy original avatar into new folder + avatar.avatar.save(os.path.basename(new_path), + File(open(media_path))) + avatar.save() + + # delete old folder and thumbnails + i = original_path.find('/', len(avatar_path) + 1) + folder = original_path[0:i] + if folder[0:1] == "/": + folder = folder[1:] + folder = os.path.join(settings.BASE_DIR, folder) + print("Delete useless folder %s" % folder) + shutil.rmtree(folder) + have_change = True + + # generate all default thumbnails in new folder + if have_change: + call_command('rebuild_avatars') + else: + print("No change ;)") diff --git a/avatar/models.py b/avatar/models.py index 7b76ac8..46148be 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -25,11 +25,14 @@ avatar_storage = get_storage_class(settings.AVATAR_STORAGE)() def avatar_file_path(instance=None, filename=None, size=None, ext=None): tmppath = [settings.AVATAR_STORAGE_DIR] + userdirname = get_username(instance.user) + if settings.AVATAR_USERID_AS_USERDIRNAME: + userdirname = str(instance.user_id) if settings.AVATAR_HASH_USERDIRNAMES: - tmp = hashlib.md5(get_username(instance.user)).hexdigest() - tmppath.extend([tmp[0], tmp[1], get_username(instance.user)]) + tmp = hashlib.md5(userdirname).hexdigest() + tmppath.extend([tmp[0], tmp[1], userdirname]) else: - tmppath.append(get_username(instance.user)) + tmppath.append(userdirname) if not filename: # Filename already stored in database filename = instance.avatar.name diff --git a/docs/index.txt b/docs/index.txt index 3eed185..1315e67 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -32,19 +32,19 @@ that are required. A minimal integration can work like this: 1. List this application in the ``INSTALLED_APPS`` portion of your settings file. Your settings file will look something like:: - + INSTALLED_APPS = ( # ... 'avatar', ) 2. Update your database:: - + python manage.py syncdb 3. Add the avatar urls to the end of your root urlconf. Your urlconf will look something like:: - + urlpatterns = patterns('', # ... (r'^avatar/', include('avatar.urls')), @@ -52,20 +52,20 @@ that are required. A minimal integration can work like this: 4. Somewhere in your template navigation scheme, link to the change avatar page:: - + Change your avatar 5. Wherever you want to display an avatar for a user, first load the avatar template tags:: - + {% load avatar_tags %} - + Then, use the ``avatar`` tag to display an avatar of a default size:: - + {% avatar user %} - + Or specify a size (in pixels) explicitly:: - + {% avatar user 65 %} Template tags and filter @@ -112,6 +112,12 @@ AVATAR_STORAGE_DIR non-filesystem storage device, this will simply be appended to the beginning of the file name. +AVATAR_USERID_AS_USERDIRNAME + By default, ``User.username`` will be use as directory name under ``AVATAR_STORAGE_DIR`. + If set to ``True``, ``User.id`` wil be use instead of ``User.username``. + Usefull if user can change his username into app to avoid duplicate content. + Defaults to ``False``. + AVATAR_GRAVATAR_BACKUP A boolean determining whether to default to the Gravatar service if no ``Avatar`` instance is found in the system for the given user. Defaults to @@ -127,22 +133,30 @@ AVATAR_GRAVATAR_FIELD user's gravatar in ``user.gravatar``. AVATAR_ALLOWED_MIMETYPES - Limit allowed avatar image uploads by their actual content payload and what - image codecs we wish to support. This limits website user content site - attack vectors against image codec buffer overflow and similar bugs. - `You must have python-imaging library installed `_. - Suggested safe setting: ``("image/png", "image/gif", "image/jpeg")``. - When enabled you'll get the following error on the form upload *File content is invalid. - Detected: image/tiff Allowed content types are: image/png, image/gif, image/jpg*. + Limit allowed avatar image uploads by their actual content payload and what + image codecs we wish to support. This limits website user content site + attack vectors against image codec buffer overflow and similar bugs. + `You must have python-imaging library installed `_. + Suggested safe setting: ``("image/png", "image/gif", "image/jpeg")``. + When enabled you'll get the following error on the form upload *File content is invalid. + Detected: image/tiff Allowed content types are: image/png, image/gif, image/jpg*. Management Commands ------------------- -This application does include one management command: ``rebuild_avatars``. It -takes no arguments and, when run, re-renders all of the thumbnails for all of -the avatars for the pixel sizes specified in the ``AUTO_GENERATE_AVATAR_SIZES`` -setting. +This application does include two management command: ``rebuild_avatars`` and ``migrate_avatars``. + +rebuild_avatars + It takes no arguments and, when run, re-renders all of the thumbnails for all of + the avatars for the pixel sizes specified in the ``AUTO_GENERATE_AVATAR_SIZES`` + setting. + +migrate_avatars + It takes no arguments and, when run, check all avatar userdirname folders. + If folder doesn't correspond with actual userdirname pattern (affect with options like + ``AVATAR_USERID_AS_USERDIRNAME`` or ``AVATAR_HASH_USERDIRNAMES``), it move avatar files to the right place, + call ``rebuild_avatars`` and delete useless folders. .. _pip: http://www.pip-installer.org/