【问题标题】:Is django-filter FilterSet behavior consistent with native Django behavior for queries spanning multi-valued relationships?django-filter FilterSet 行为是否与跨多值关系的查询的原生 Django 行为一致?
【发布时间】:2020-12-11 23:47:39
【问题描述】:

我正在尝试通过收件人模型查询用户的所有未读消息(即每条消息都有许多具有已读属性的收件人)。使用模型管理器运行时,查询按预期工作。例如:

Message.objects.filter(**{"recipients__user_id": 1, "recipients__read": False })

但是,当使用 FilterSet(使用 django-filter 版本 2.3.0)运行时,查询包括用户收到的所有消息,无论读取状态如何。例如:

MessageFilter(data={"recipients__user_id": "1", "recipients___read": False }).qs

这是消息过滤器:

class MessageFilter(FilterSet):
    class Meta:
        model = Message
        exclude = ('deleted_at', )
        fields = ('chat_id', 'recipients__user_id', 'recipients__read', )
        filter_overrides = {
          # NOTE: enables support for querying pk rather than relay uuid
          models.ForeignKey: { 'filter_class': LocalIDFilter },
        }

    # NOTE: enables mapping from camelcase to snakecase
    order_by = OrderingFilter(fields=(('created_at', 'createdAt'),),)

有人知道我的实现是否不正确,或者这只是所需的库行为(我无法从文档中得知)?此外,任何建议的解决方法将不胜感激。除了手动覆盖 FilterSet 上的 qs 属性之外,我没有看到任何更好的解决方案。

【问题讨论】:

    标签: python django django-models django-filter graphene-django


    【解决方案1】:

    我一直在研究源代码,但似乎库的实现不一致(尽管这可能是经过深思熟虑的设计决定)。但是,我可以通过使用以下内容覆盖 filter_queryset 方法来实现我想要的过滤器:

    class MessageFilter(FilterSet):
        
        ...
        
        def filter_queryset(self, queryset):
            queryset = queryset.filter(**{k: v for k, v in self.form.cleaned_data.items() if v is not None})
            assert isinstance(queryset, models.QuerySet), \
                "Expected '%s.%s' to return a QuerySet, but got a %s instead." \
                % (type(self).__name__, name, type(queryset).__name__)
    
            # NOTE: native implementation
            # for name, value in self.form.cleaned_data.items():
            #     queryset = self.filters[name].filter(queryset, value)
            #     assert isinstance(queryset, models.QuerySet), \
            #         "Expected '%s.%s' to return a QuerySet, but got a %s instead." \
            #         % (type(self).__name__, name, type(queryset).__name__)
            
            return queryset
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 2020-09-17
      • 2016-06-10
      • 1970-01-01
      • 2014-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多