You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework实现依赖关联模型的自定义只读active字段

解决方案

你不需要重写视图的list方法,通过调整查询集和序列化器即可实现需求,以下是两种可行方案:

方案1:查询集注解注入字段(最高效,推荐)

通过Django的annotate方法直接将关联的active字段注入到Notification查询结果中,一次查询即可获取所有需要的数据,无额外数据库开销:

  1. 调整视图的get_queryset方法:
from django.db.models import F

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
        ).annotate(
            # 直接将关联的active字段注解到Notification对象上
            active=F('notificationuserlink__active')
        )
  1. 修改序列化器新增active字段:
class NotificationSerializer(serializers.ModelSerializer):
    # 只读字段,承接注解注入的active值
    active = serializers.BooleanField(read_only=True)
    class Meta:
        model=Notification
        fields=("value", "active")

方案2:SerializerMethodField实现

如果不想修改查询集,也可以通过序列化器的方法字段实现,注意要提前预加载关联数据避免N+1查询问题:

  1. 调整查询集添加预加载:
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
        ).prefetch_related('notificationuserlink_set')
  1. 修改序列化器:
class NotificationSerializer(serializers.ModelSerializer):
    active = serializers.SerializerMethodField()
    
    def get_active(self, obj):
        current_user = self.context['request'].user
        # 因为存在唯一约束,直接取唯一的关联记录即可
        return obj.notificationuserlink_set.get(user=current_user).active

    class Meta:
        model=Notification
        fields=("value", "active")

额外优化建议

后续你可以直接在NotificationUserLink模型中添加联合唯一约束,在数据库层面保证关联关系唯一:

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)

    class Meta:
        unique_together = ('user', 'notification')

内容的提问来源于stack exchange,提问作者Neil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 02:48:02