【问题标题】:DRF Filter PrimaryKeyField Based on Current User基于当前用户的 DRF 过滤 PrimaryKeyField
【发布时间】:2020-06-30 17:00:15
【问题描述】:

我有一个视图设置为向用户返回书籍列表,该列表是从基于当前登录用户的简单书籍模型中检索的。但是,我也有 ReadingSession 模型,它与 Book 和 User 都有外键关系。

当我为用户检索书籍时,我至少希望返回一个主键列表,我可以使用这些主键在我的客户端中获取长度。

以下代码将在我的 BookSerializer 中获取完整的阅读会话集:

from rest_framework import serializers
from books.models import Book


class BookSerializer(serializers.ModelSerializer):
    readingsession_set = serializers.PrimaryKeyRelatedField(
        many=True, read_only=True)

    class Meta:
        model = Book
        fields = ["id", "title", "author", "publisher",
                  "publish_date", "description", "category",
                  "language", "small_thumbnail", "thumbnail",
                  "readingsession_set"]

但是,这样做的问题是它会返回所有阅读会话,而不管会话是否属于该用户。

我希望能够对其进行过滤,以便它只返回当前用户的阅读会话。大致如下:

readingsession_set = serializers.PrimaryKeyRelatedField(queryset=ReadingSession.objects.filter(user=user), read_only=True)

但我尝试了各种尝试从​​ APIView 传递用户 (self.request.user) 的方法,但似乎都不起作用。我尝试过传递上下文,并尝试在 __init__ 中传递额外的 **kwargs,但似乎都没有。

有没有办法做到这一点?还是我采取了错误的方法?

谢谢

【问题讨论】:

    标签: django-rest-framework


    【解决方案1】:

    用户不在序列化程序的声明中,而是在其实例化期间。 因此,您可以在__init__ 方法中按用户过滤querysets。

    from rest_framework import serializers
    
    from bar.models import Foo
    
    
    class RandomSerializer(serializers.Serializer):
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            user_foos = Foo.objects.filter(user=self._user)
            self.fields['foo_ids'] = serializers.PrimaryKeyRelatedField(
                required=False,
                many=True,
                read_only=False,
                queryset=user_foos,
                default=user_foos)
    
        @property
        def _user(self):
            request = self.context.get('request', None)
            if request:
                return request.user
    

    不要忘记将request 对象传递给上下文中的序列化程序(如有必要,例如,使用简单的APIView

    from rest_framework import views
    
    
    class RandomView(views.APIView):
        serializer_class = RandomSerializer
    
        def post(self, request):
            serializer = self.serializer_class(
                data=request.data, context={'request': request}) 
            # ...
    
    serializer = RandomSerializer(data=request.data, context={'request': request}
    

    【讨论】:

      【解决方案2】:

      您可以通过context 访问序列化程序上请求的用户。

      如文档中所述,您始终可以这样做:

      serializer = AccountSerializer(account, context={'request': request})
      

      因此,您将能够在序列化程序中使用self.context['request'].user

      希望这就是你所追求的。

      【讨论】:

      • 我试过这个 - serializer = ReadingListSerializer(book_list, many=True, context={"request": self.request}) 但是,当我尝试访问序列化程序中的上下文时,它是一个空字典
      • 您使用的是 APIView 还是视图集?
      • 你能用调用这个序列化程序的 ListView 更新问题吗?
      • 我正在使用 APIView。我设法通过了上下文,但是它似乎没有帮助,因为我无法从方法中访问self。意思是,我做不到readingsession_set = serializers.PrimaryKeyRelatedField(queryset=ReadingSession.objects.filter(user=self.context["request"].user), read_only=True)
      猜你喜欢
      • 1970-01-01
      • 2021-08-11
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      • 2022-11-30
      • 1970-01-01
      • 2011-04-22
      • 2019-03-16
      相关资源
      最近更新 更多