Django Rest Framework 针对不同帐户层的不同映像大小(基本、高级)

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

提问人:Robert Bielicki 提问时间:2/13/2023 最后编辑:Robert Bielicki 更新时间:2/21/2023 访问量:440

问:

有三个 bultin 帐户层:基本、高级和企业: 上传图片后拥有“基本”计划的用户将获得:

  • 指向高度为 200 像素的缩略图的链接 拥有“高级”计划的用户可获得:
  • 指向高度为 200 像素的缩略图的链接
  • 指向高度为 400px 的缩略图的链接
  • 指向最初上传的图片的链接

我不知道如何结合保存用户根据其成员身份添加的不同分辨率照片的功能。 我的解决方案为所有用户保存一个分辨率。

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)

python django django-rest-framework 成员

评论


答:

1赞 user510170 2/17/2023 #1

我认为您需要扩展模型并以所有分辨率将图像保存在数据库中:

# 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)

然后,您需要根据用户权限添加序列化,如下所示:

# 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')

然后根据用户的权限通过重写 get_serializer_class 方法来序列化数据,如下所示:

# 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)