【问题标题】:Django FilterSet AND(?) conditionDjango FilterSet AND(?) 条件
【发布时间】:2015-12-09 13:36:00
【问题描述】:

我正在创建一个应用程序,其中食物有多个成分,每个成分都有特定的价值。我希望能够根据特定成分的价值过滤食物。

这是我的模型:

class Food(models.Model):
    id = models.AutoField(primary_key=True, db_column="id")
    name = models.CharField(max_length=150)
    product_type = models.CharField(max_length=150)

class Component(models.Model):

    id = models.AutoField(primary_key=True, db_column="id")
    name = models.CharField(max_length=150)
    value = models.FloatField()
    food = models.ForeignKey(Food, related_name='food_components', related_query_name='food_components')

然后我定义过滤器集和视图

import rest_framework_filters as filters

class ComponentFilter(filters.FilterSet):

    name = filters.CharFilter(name="name")
    val = filters.NumberFilter(name="value", distinct=True)
    minval = filters.NumberFilter(name="value", lookup_type="gte", distinct=True)
    maxval = filters.NumberFilter(name="value", lookup_type="lte", distinct=True)

    class Meta:
        model = Component

class FoodFilter(filters.FilterSet):

    name = filters.CharFilter(name='name')
    product_type = filters.CharFilter(name='product_type')
    components = filters.RelatedFilter(ComponentFilter, name='food_components')

    class Meta:
        model = Food

class FoodViewSet(viewsets.ModelViewSet):

    queryset = Food.objects.all()
    serializer_class = FoodSerializer
    filter_class = FoodFilter

我希望能够使用相关模型中的多个字段(结合两个参数)来过滤视图集。像http://whatever/foods/components__name=X&components__value=1 这样的东西会让我得到所有元素 X 值为 1 的食物。我正在使用 django-rest-framework-filters (https://github.com/philipn/django-rest-framework-filters)

据我所知,由于所有食物都具有所有元素,因此 components__name 无关紧要,我将获得所有具有任何值为 1 的组件的食物。如何将两者结合起来?

提前致谢!

【问题讨论】:

  • 您是否正在寻找像this 这样的多字段过滤器?
  • 根据我对您提供的示例的理解,它将返回包含这些值的任何字段(更像是 OR 关系),而我有兴趣能够在一个 URL 中指定两个过滤器, 但让它们像 AND 条件一样组合在一起。
  • 那么你想要(a__name=X OR b_name=X OR c_name = X) AND ( a__value=1 OR b_value=1 or c_value=1) 还是想要(a__name=X AND a_value=1) OR (b_name=X and b_value=1) OR (c_name=X AND c_value=1)
  • 这将是一个比我想做的更复杂的查询。其实就是a__name=X AND a__value=1这个很简单的例子。但我想知道是否可以通过 filterset 使用 url 参数来做到这一点。

标签: python django django-rest-framework


【解决方案1】:

您需要创建一个新过滤器来处理与给定Component 相关的单个 Food 对象上的nameval 对:

class FoodComponentFilter(django_filters.Filter):
    def filter(self, qs, value):
        strs = value.split(',')
        if len(strs) != 2:
            raise Exception
        return qs.filter(
            food_components__in = Component.objects.filter(
                name=strs[0],
                value=float(strs[1])
            )
        )

FoodFilter 中实例化这个:

class FoodFilter(filters.FilterSet):
   component_food_pair = FoodComponentFilter(name='dummy_field')
   [...]
   class Meta:
        model = Food
        fields = ('component_food_pair',[...])

然后,像这样使用它:

?component_food_pair=Foo,42.0

【讨论】:

  • 谢谢!不得不稍微调整一下 qs.filter return qs.filter( food_components__in = Food.objects.filter( food_components__name=strs[0], food_components__value=float(strs[1]) ) ) 如果您将编辑添加到您的回复中,我会将其设置为正确的:)
  • 糟糕。我有一个巨大的错误。嵌套过滤器应该是模型类型Component,而不是Food。以前我是根据Foodid 过滤Components 的——非常错误。添加了float 转换。
猜你喜欢
  • 1970-01-01
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2023-02-26
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 2015-09-25
相关资源
最近更新 更多