pythondjangodjango-modelsdjango-rest-frameworkmembership

Django Rest Framework different image size for different account tiers (Basic, Premium)


There are three bultin account tiers: Basic, Premium and Enterprise: Users that have "Basic" plan after uploading an image get:

I have no idea how I can combine the ability to save different resolutions of photos added by the user depending on their membership. My solution saves one resolution for all users.

models.py

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from PIL import Image


def user_directory_path(instance, filename):
    return 'images/{0}'.format(filename)


class Images(models.Model):

    title = models.CharField(max_length=250)
    image = models.ImageField(upload_to=user_directory_path)
    created = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.PROTECT, related_name='author')

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

        img = Image.open(self.image.path)

        if img.height > 200:
            output_size = (200, 200)
            img.thumbnail(output_size)
            img.save(self.image.path)


class Profile(models.Model):

    MEMBERSHIP = (
        ('BASIC', 'Basic'),
        ('PREMIUM', 'Premium'),
        ('ENTERPRISE', 'Enterprise')
    )

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    membership = models.CharField(max_length=10, choices=MEMBERSHIP, default='BASIC')

    def __str__(self):
        return f'{self.user.username} {self.membership} Profile'

serializers.py

from rest_framework import serializers
from blog.models import Images, Profile



class ImagesSerializer(serializers.ModelSerializer):

    class Meta:
        model = Images
        fields = ('author', 'title', 'image')


views.py

class ImagesViewSet(viewsets.ModelViewSet):

    queryset = Images.objects.all()
    serializer_class = ImagesSerializer

    def get_queryset(self):

        user = self.request.user
        return Images.objects.filter(author=user)


Solution

  • I think you need to expand your model and save images in the database in all resolutions:

    # models.py
    class Images(models.Model):
    
        title = models.CharField(max_length=250)
        image = models.ImageField(upload_to=user_directory_path)
        image_200 = models.ImageField(upload_to=user_directory_path_200)
        image_400 = models.ImageField(upload_to=user_directory_path_200)
        
        def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
    
            img_200 = Image.open(self.image.path)
            img_400 = Image.open(self.image.path)
    
            output_size_200 = (200, 200)
            output_size_400 = (400, 400)
            img_200.thumbnail(output_size_200)
            img_400.thumbnail(output_size_400)
            img_200.save(self.image_200.path)
            img_400.save(self.image_400.path)
    

    Then you need to add serialization depending on user privileges, something like this:

    # serializers.py
    class ImagesBasicUserSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Images
            fields = ('author', 'title', 'image_200')
    
    
    class ImagesPremiumUserSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Images
            fields = ('author', 'title', 'image_200', 'image_400', 'image')
    

    And then serialize the data depending on the user's privileges by overriding the get_serializer_class method in the likeness of this:

    # views.py
    class ImagesViewSet(viewsets.ModelViewSet):
    
        queryset = Images.objects.none()
        serializer_class = ImagesBasicUserSerializer
        
        def get_user(self):
            
            user = self.request.user
            return user
    
        def get_serializer_class(self):
            
            user = self.get_user()
            if user.membership == 'Basic':
                return ImagesBasicUserSerializer
            if user.membership == 'Premium':
                return ImagesPremiumUserSerializer
        
        def get_queryset(self):
    
            user = self.get_user()
            return Images.objects.filter(author=user)