You need to enable JavaScript to run this app. Django Rest Framework序列化器判断用户是否在多对多blocked字段中
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework序列化器判断用户是否在多对多blocked字段中

实现方案

方案1:使用SerializerMethodField(实现最简单)

直接修改序列化器即可,无需改动视图代码:

from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    # 声明为序列化方法字段,默认只读
    is_blocked = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ['id', 'email', 'user_type', 'is_blocked']
    
    def get_is_blocked(self, obj):
        # 从序列化器上下文获取当前登录用户
        current_user = self.context['request'].user
        # 检查被查询用户是否在当前用户的拉黑列表中,用exists()优化查询性能
        return current_user.blocked.filter(pk=obj.pk).exists()

DRF的视图默认会把request对象注入到序列化器的context中,因此可以直接通过self.context['request']拿到当前请求的登录用户。


方案2:数据库层注解(性能更优)

如果接口流量较高,或者需要批量序列化多个用户(比如列表接口),推荐在查询时直接通过注解计算is_blocked字段,避免序列化时的N+1查询问题:
首先修改视图代码:

from django.db.models import Exists, OuterRef
from rest_framework import generics, permissions
from rest_framework_simplejwt import authentication

class UserDetail(generics.RetrieveAPIView):
    authentication_classes = (authentication.JWTAuthentication,)
    permission_classes = (permissions.IsAuthenticated,)

    serializer_class = UserSerializer
    
    def get_queryset(self):
        current_user = self.request.user
        return User.objects.annotate(
            # 直接在数据库层判断当前查询用户是否在登录用户的拉黑列表中
            is_blocked=Exists(current_user.blocked.filter(pk=OuterRef('pk')))
        )

序列化器保持基础声明即可,只需加上read_only=True:

class UserSerializer(serializers.ModelSerializer):
    # 直接读取queryset注解的is_blocked字段,声明为只读
    is_blocked = serializers.BooleanField(read_only=True)

    class Meta:
        model = User
        fields = ['id', 'email', 'user_type', 'is_blocked']

该方案仅需执行1次数据库查询就能拿到所有需要的数据,性能明显优于方案1,尤其适合多数据序列化的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 17:36:04