【问题标题】:How to programmatically provide `queryset` to PrimaryKeyRelatedField in DRF 3如何以编程方式向 DRF 3 中的 PrimaryKeyRelatedField 提供`queryset`
【发布时间】:2015-01-14 15:56:58
【问题描述】:

为了拥有非只读的PrimaryKeyRelatedField,您需要提供一个包含有效选项的查询集。

如何根据当前请求(用户)正确填充该查询集?

【问题讨论】:

    标签: django-rest-framework


    【解决方案1】:

    关键是继承PrimaryKeyRelatedField并重载get_queryset方法,使用来自请求上下文的用户信息:

    class UserFilteredPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
        def get_queryset(self):
            request = self.context.get('request', None)
            queryset = super(UserFilteredPrimaryKeyRelatedField, self).get_queryset()
            if not request or not queryset:
                return None
            return queryset.filter(user=request.user)
    

    然后您可以像使用(未过滤的)原始序列化程序一样使用这个新的序列化程序:

    class MySerializer(serializers.ModelSerializer):
        related = UserFilteredPrimaryKeyRelatedField(queryset=MyModel.objects)
    

    每当序列化程序访问查询集时,都会对其进行过滤,以便仅返回当前用户拥有的对象。

    【讨论】:

    • 我不知道为什么这不是公认的答案。这是唯一能回答问题的人。
    • 这应该被标记为答案。我只会在 if 中添加另一个条件:or not request.user.is_authenticated,因此当没有用户登录时它返回 None 而不是异常
    • 我无法在序列化程序中获取上下文,尽管在视图中覆盖了 get_serializer_context()。任何关于这方面的建议都会很有帮助。
    • 更新:通过调用 get_serializer() 而不是 get_serializer_class() 能够正确获取上下文,但现在序列化程序上的查询集没有被过滤。它只采用在 serailizer 上声明字段时使用的默认(全部)查询集。在序列化程序的 get_queryset() 中放置一个调试器,但代码没有命中该部分,我不明白为什么。任何指针都会有所帮助。
    • 对于那些苦苦挣扎的人,这里有一个简单的例子:medium.com/django-rest-framework/…
    【解决方案2】:

    视图有一个

    self.request.user
    

    属性,然后您可以使用它来获取与用户相关的查询集 例如

    queryset = Products.objects.get(customer=self.request.user)
    

    【讨论】:

    • 如何在序列化器的类级别访问视图?
    • 你不能。您可以覆盖 Serializer 类的 init 以从 self.context 获取视图,甚至可以修改视图以将登录用户传递给序列化器上下文并使用它。第二种方法更好,因为您可以单独测试 Serializer 而无需创建视图。
    • @Fatima 请求对象没有直接暴露在序列化器中,解决方法是上下文。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 2019-05-06
    • 2010-11-20
    • 2011-04-03
    相关资源
    最近更新 更多