【问题标题】:Django REST Framework: How to combine two querysets?Django REST Framework:如何组合两个查询集?
【发布时间】:2017-06-04 05:39:49
【问题描述】:

我正在尝试组合两个在对象中引用 FK 的过滤器,但我得到了错误和冗余的数据。

下面展示了位于views.py中的过滤器:

class RecordFilter(df.FilterSet):
    user = df.CharFilter(name='active_states__user', method='filter_user')
    activestate = df.BooleanFilter(name='active_states__is_active', method='filter_is_active')

    class Meta:
        model = Record
        fields = ['type', 'group', 'user', 'activestate']

    def filter_user(self, queryset, _, value):
        return queryset.filter(active_states__user_id=value)

    def filter_is_active(self, queryset, _, value):
        return queryset.filter(active_states__is_active=value)

例如,在我的测试用例中,我创建了 4 个记录对象,并在其中添加了 activestate 和 user。

record1.set_active_states_for_users([user1.uuid], True)
record2.set_active_states_for_users([user1.uuid], False)
record2.set_active_states_for_users([user2.uuid], True)
record3.set_active_states_for_users([user2.uuid], False)

我尝试针对 user=user2 和 activestate=True 测试这些过滤器。 我得到了:

  • 由于 activestate=True 和 user=user2 是 record2 的两倍
  • 一次record3因为user=user2

结果应该只有记录2。

我注意到chain 可以连接查询集,但我不知道如何在 RecordFilter 类的views.py 中使用它。你有什么线索吗?

【问题讨论】:

  • 如果record2.set_active_states_for_users([user1.uuid], False) 而你过滤activestate=True,为什么结果应该是record2?
  • 如果user = df.CharFilter,你为什么要做queryset.filter(active_states__user_id=value)?在您的情况下,您根本不需要 method args。您的过滤器逻辑在字段定义和方法中重复。 name arg 的作用类似于过滤语句。
  • 结果应该只有记录 2,因为它是唯一涵盖(第 3 行)record2.set_active_states_for_users([user2.uuid], True) 两个过滤器的记录。另外,在您的第二条评论中,您的意思是当您提交定义和方法时,也许您会得到重复?

标签: python django django-rest-framework django-queryset django-filter


【解决方案1】:

您有描述here的情况。可以实现这个 API:

class RecordFilter(df.FilterSet):
    active_user = df.CharFilter(method='filter_active_user')
    disabled_user = df.CharFilter(method='filter_disabled_user')

    class Meta:
        model = Record
        fields = ['type', 'group', 'user']

def filter_active_user(self, queryset, name, value):
    return queryset.filter(active_states__is_active=True,
                           active_states__user_id=value)

def filter_disabled_user(self, queryset, name, value):
    return queryset.filter(active_states__is_active=False,
                           active_states__user_id=value)

因此,您可以过滤任何、仅禁用和仅启用的用户。 查询 active_user=user2 将只返回 record2。

但我不知道你为什么要使用CharFilter 代替user 并过滤查询集,如active_states__user_id=value。如果id 不是字符串,则看起来像错误。

【讨论】:

  • 我正在使用 ChalrFilter 因为用户的 id 是一个字符串。对于上述问题,您的解决方案部分正确,但如果我想添加更多过滤器,如类型或组,我将遇到同样的问题,我将不得不创建许多其他变量,如 filter_active_user_groupfilter_disabled_user_group以避免错误的结果。所以我认为我需要一个通用的解决方案来组合这些查询集。
猜你喜欢
  • 2018-09-24
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 2019-08-11
  • 2016-09-30
  • 2017-12-04
  • 1970-01-01
  • 2018-06-17
相关资源
最近更新 更多