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",)
假设 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",)