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

如何基于用户is_staff状态过滤Django序列化器中的嵌套Book对象

解决方案

方法一:通过序列化器的SerializerMethodField实现过滤

这种方式直接在序列化器中根据用户权限动态过滤书籍,实现简单直观:

修改BookCategorySerializer,将固定的books字段替换为SerializerMethodField,然后在对应的方法里根据当前用户的is_staff状态过滤书籍:

class BookCategorySerializer(serializers.ModelSerializer):
    """
    Serialize books by category
    """
    books = serializers.SerializerMethodField()

    class Meta:
        model = BookCategory
        fields = (
            'name',
            'active',
            'books',
        )

    def get_books(self, obj):
        # 从序列化器上下文获取当前请求的用户
        user = self.context['request'].user
        # 根据用户状态过滤书籍
        if user.is_staff:
            books = obj.book_set.all()
        else:
            books = obj.book_set.filter(active=True)
        # 使用BookSerializer序列化过滤后的书籍
        return BookSerializer(books, many=True).data

视图集不需要修改,ReadOnlyModelViewSet默认会将request传入序列化器的context中,供我们获取用户信息。

方法二:在视图集中通过预取关联优化性能

如果你的书籍数据量较大,方法一可能会导致N+1查询问题(每个分类单独查询一次书籍)。这种情况下,建议在视图集的get_queryset方法中,结合Prefetch对象动态预取过滤后的书籍,提升性能:

首先修改视图集:

from django.db.models import Prefetch

class BookCategoryViewSet(viewsets.ReadOnlyModelViewSet):
    """
    View available books by category
    """
    serializer_class = BookCategorySerializer

    def get_queryset(self):
        user = self.request.user
        # 根据用户状态定义预取的书籍查询集
        if user.is_staff:
            book_prefetch = Prefetch('book_set', queryset=Book.objects.all())
        else:
            book_prefetch = Prefetch('book_set', queryset=Book.objects.filter(active=True))
        # 预取过滤后的书籍,避免N+1查询
        return BookCategory.objects.all().prefetch_related(book_prefetch)

然后保持原来的BookCategorySerializer不变即可:

class BookCategorySerializer(serializers.ModelSerializer):
    """
    Serialize books by category
    """
    books = BookSerializer(many=True, read_only=True, source='book_set')

    class Meta:
        model = BookCategory
        fields = (
            'name',
            'active',
            'books',
        )

这种方式提前在数据库层面完成了书籍的过滤和预取,性能更优,适合数据量较大的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:57:14