jazzband / sorl-thumbnail

Thumbnails for Django
https://sorl-thumbnail.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.74k stars 496 forks source link

Upload To Media Root Under User's Own Username Folder #641

Open jaradc opened 4 years ago

jaradc commented 4 years ago
# models.py
from sorl.thumbnail import ImageField

def featured_images_folder(instance, filename):
    # docs to why this works: https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.FileField.upload_to
    return "{}/featured-images/{}".format(instance.user.username, filename)

class Post(models.Model):
    ...
    featured_image = ImageField(upload_to=featured_images_folder, blank=True)

I am overriding the ThumbnailBackend to be more SEO-friendly (code found on MicroPyramid):

from sorl.thumbnail.conf import settings
from sorl.thumbnail.helpers import tokey, serialize
import os.path

class SEOThumbnailBackend(ThumbnailBackend):

    def _get_thumbnail_filename(self, source, geometry_string, options):
        """
        Computes the destination filename.
        """
        key = tokey(source.key, geometry_string, serialize(options))

        filename, _ext = os.path.splitext(os.path.basename(source.name))

        path = '%s/%s' % (key, filename)
        return '%s%s.%s' % (settings.THUMBNAIL_PREFIX, path, EXTENSIONS[options['format']])
THUMBNAIL_BACKEND = 'myapp.thumbnail.SEOThumbnailBackend'

The settings.THUMBNAIL_PREFIX is the reason files are being uploaded to a cache/ directory.

First Question The image that the user uploads does go to my upload_to= directory, but the ... I guess, cached images go to a folder in my media root named cache. Is this best-practice? Or should the uploaded image and its cached siblings be together?

Second Question I want my media root directory to have folders for every user. This means, I'd like to have everything related to that user under one directory. How would I set the current TEMPLATE_PREFIX (cache/) to upload inside of a user's username folder in the media root?

# settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')

Ex user with username "jason1" uploads an image. It gets uploaded to either:

mediaroot / username / featured_images / put stuff here
uploads/jason1/featured_images/{ let sorl thumbnail do what it does here }

or

mediaroot / username / featured_images / cache / put stuff here
uploads/jason1/featured_images/cache/{ let sorl thumbnail do what it does here }
jaradc commented 4 years ago

TLDR;

How do I upload to a folder structure like this where the username is the name of my user:

uploads # <-- my mediaroot folder
    username1
        featured_images
            cache
    username2
        featured_images
            cache

I want to put the cache folder under a username within my mediaroot...

skiv23 commented 4 years ago

You need to parse image source and get path to user directory and then use it as a prefix for your final result:

class SEOThumbnailBackend(ThumbnailBackend):

    def _get_thumbnail_filename(self, source, geometry_string, options):
        """
        Computes the destination filename.
        """
        key = tokey(source.key, geometry_string, serialize(options))

        filename, _ext = os.path.splitext(os.path.basename(source.name))

        path = '%s/%s' % (key, filename)
        # trim filename to get original path to user's folder
        user_prefix_path = '/'.join(source.name.split('/')[:-1])
        return '%s/%s%s.%s' % (user_prefix_path, settings.THUMBNAIL_PREFIX, path, EXTENSIONS[options['format']])

image

jaradc commented 4 years ago

Thanks, I did something very similar.