Django Rest Framework 自定义只读字段依赖于相关模型

Django Rest Framework custom readonly field dependant on related model

假设 models.py 像:

class User(AbstractUser):
    pass

class Notification(models.Model):
    value = models.CharField(max_length=255)

class NotificationUserLink(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    notification = models.ForeignKey(Notification, on_delete=models.CASCADE)
    active = models.BooleanField(default=True)

规范化而不只是在通知本身上有一个用户字段的意义在于,当我想向数百人发送相同的通知时,我只需要 1 个通知对象。假设我在 views.py 中也有一个端点,如下所示,用户可以看到他们所有的通知,并且只能看到他们的通知,这是通过过滤查询集来实现的。

class NotificationViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.NotificationSerializer
    model = Notification
    lookup_field='pk'
    def get_queryset(self):
        user = self.request.user
        return Notification.objects.filter(notificationuserlink__user=user)

现在,NotificationUserLink 模型上的“用户”和“通知”对形成了一个候选键(它们在一起是唯一的。目前只是根据业务逻辑,但我会在某个时候将实际约束添加到数据库中)。

因此,给定请求中的用户,每个通知(在过滤的查询集中)将有 1 个且只有 1 个指向该用户的 NotificationUserLink。因此,从用户的角度来看,该通知是否处于活动状态,具体取决于 NotificationUserLink 上的“活动”字段。

我想要完成的是将该字段(“活动”)包含在通知的序列化中。 IE。如果用户点击此端点,他们应该会看到如下通知:

[
{
    "value": "Bob commented on your post",
    "active": False
},
{...}, ...
]
etc

我认为要实现这一点,我需要重写视图上的“列表”方法。但我不知道怎么办。序列化程序在列表方法中传递了一个查询集,所以我不确定如何将数据注入其中。

序列化程序目前看起来像这样:

class NotificationSerializer(serializers.ModelSerializer):
    class Meta:
        model=Notification
        fields=("value",)

您可以在您的查询集中 annotate link 的状态:

Notification.objects.filter(
    notificationuserlink__user=user
).annotate(
    active=F('notificationuserlink__active')
)

然后你可以在你的序列化器中添加一个只读字段active字段:

class NotificationSerializer(serializers.ModelSerializer):
    active = serializers.BooleanField(read_only=True)
    class Meta:
        model = Notification
        fields = ("active", "value",)