在 django rest 框架中的另一个模型的 modelSerializer 中检索模型的最后一个实例

retrieving the last instance of a model in another model's modelSerializer in django rest framework

我正在为一个网站创建休息 APIs,用户可以在其中购买所提供的订阅之一。

本网站有一个用户信息 API,其中 return 是有关登录用户的信息,可用于在网站上显示他们的信息。 问题是,提到的 API 的序列化程序是“用户”模型上的 modelSerializer,而我想要 return 的信息是“订阅”模型的实例,它是“的最新实例” SubPurchase”模型指的是。

这些是我的序列化程序、模型和 views.And 我需要以某种方式 return 用户当前订阅的 ID 和名称以及用户信息。如果还有什么问题,可以在评论里问我,我会一一解答。

# models.py
class User(AbstractBaseUser, PermissionsMixin):
    userID = models.AutoField(primary_key=True)
    username = models.CharField(max_length=100, unique=True, validators=[RegexValidator(regex="^(?=[a-z0-9._]{5,20}$)(?!.*[_.]{2})[^_.].*[^_.]$")])
    email= models.EmailField(max_length=100, unique=True,  validators=[EmailValidator()])
    name = models.CharField(max_length=100)
    isSuspended = models.BooleanField(default=False)
    isAdmin = models.BooleanField(default=False)
    emailActivation = models.BooleanField(default=False)
    balance = models.IntegerField(default=0)

    objects = UserManager()

    USERNAME_FIELD = 'username'


class Subscription(models.Model):
    subID = models.AutoField(primary_key=True)
    nameOf = models.CharField(max_length=50)
    price = models.PositiveIntegerField()
    salePercentage = models.PositiveIntegerField(default=0)
    saleExpiration = models.DateTimeField(default=datetime.datetime.now, blank=True)

    def __str__(self):
        return f"{self.nameOf}"


class SubPurchase(models.Model):
    price = models.PositiveIntegerField()
    dateOf = models.DateTimeField(auto_now_add=True)
    
    user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
    subscription = models.ForeignKey(Subscription, null=True, on_delete=models.SET_NULL)
    
    def __str__(self):
        return self.subscription
# serializers.py
class UserInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = get_user_model()
        fields = ('userID', 'username','email', 'name', 'balance', 'emailActivation', 'isSuspended')
        read_only_fields = ('userID', 'username','email', 'name', 'balance', 'emailActivation', 'isSuspended')


# views.py
class UserInfoViewSet(viewsets.ModelViewSet):
    queryset = get_user_model().objects.all()
    serializer_class = UserInfoSerializer

    def get_queryset(self):
        uID = getattr(self.request.user,'userID')
        return get_user_model().objects.filter(userID=uID)

    def get_object(self):
        uID = getattr(self.request.user,'userID')
        return self.queryset.filter(userID=uID)

同样,我需要更改 UserInfoSerializer 以提供用户当前订阅的名称、ID 和到期日期(即购买日期后 30 天)

如果您只对返回的数据感兴趣,您可以覆盖序列化程序的函数 to_representation 并为相关模型创建一个序列化程序。如果我没理解错的话,您用户的当前订阅是最后一个(如果按“dateOf”排序)。所以类似的东西可以解决问题

class SubscriptionSerializer(serializers.ModelSerializer):
     class Meta:
           model = Subscription
           fields = ('nameOf', 'id', 'saleExpiration ')

class UserInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = get_user_model()
        fields = ('userID', 'username','email', 'name', 'balance', 'emailActivation', 'isSuspended')
        read_only_fields = ('userID', 'username','email', 'name', 'balance', 'emailActivation', 'isSuspended')

    def to_representation(self, instance):
         data = super().to_representation(instance)
         current_subs = instance.subpurchase_set.order_by('dateOf').last().subscription
         data['current_subscription'] = SubscriptionSerializer(instance=current_subs).data
         return data


您可以使用 NestedSerializers 来实现您正在寻找的东西

基本上,嵌套序列化是一种方法,您可以在其中 return、创建、放入...,从另一个模型进入模型,它是这样的..

models.py

class User(AbstractBaseUser, PermissionsMixin):
....
#user model data

class SubPurchase(models.Model):
   ...
  user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)

serializers.py

class SubscriptionSerializer(serializers.ModelSerializer):
     class Meta:
         model = Subscription
         fields =["anyfield you wanna include"]

class SubPurchaseSerializer(serializers.ModelSerializer):
     class Meta:
         model = SubPurchase
         fields =["anyfield you wanna include"]


class UserInfoSerializer(serializers.ModelSerializer): 
       subpurchace = SubPurchaseSerializer()
       subscription= SubscriptionSerializer() #later included in the fields of this serializer
    class Meta:
        model = get_user_model()
        fields = ('userID','subpurchace', 'subscription', 'username','email', 'name', 'balance', 'emailActivation', 'isSuspended')
        read_only_fields = ('userID', 'username','email', 'name', 'balance', 'emailActivation', 'isSuspended')