Django FilterSet AND(?)条件

时间:2015-12-09 13:36:00

标签: python django django-rest-framework

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

以下是我的模特:

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

从我看到的情况来看,由于所有食物都含有所有元素,因此组件名称无关紧要,我会得到所有含有任何成分的食物。我怎样才能将两者结合起来?

提前致谢!

1 个答案:

答案 0 :(得分:3)

您需要创建一个新的过滤器,用于处理与单个 name对象相关的valFood对给定Component

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