2017-03-01 147 views
3

我有以下(简化的)数据模型:Django的过滤对象

class Article(Model): 
    uuid = models.CharField(primary_key=True, max_length=128) 

class Attribute(Model): 
    uuid = models.CharField(primary_key=True, max_length=128) 
    article = models.ForeignKey(Article, related_name='attributes') 
    type = models.CharField(max_length=256) 
    value = models.CharField(max_length=256) 

一个示例用法是与连接到它与type="brand"value="Nike"一个属性的制品。现在我想编写一个可以获得某品牌所有文章的API,但我似乎无法为其编写过滤器。这是我到目前为止:

class PhotobookFilter(df.FilterSet): 
    brand = df.CharFilter(method='filter_brand') 

    class Meta: 
     model = Article 

    def filter_brand(self, queryset, name, value): 
     return queryset.filter('order__attributes') 

class PhotobookViewSet(AbstractOrderWriterViewSet): 
    queryset = Article.objects.all() 
    serializer_class = ArticlePhotobookSerializer 
    filter_backends = (filters.DjangoFilterBackend,) 
    filter_class = PhotobookFilter 

queryset.filter的行显然不正确呢。我需要在这里创建一个过滤器,返回包含属性为type="brand"value=value的所有文章。我将如何做到这一点?

回答

1

你确定要同时查找(typeAttributevalue)凝结成一个过滤器?为什么不允许单独对两个字段进行过滤?

E.g.

class PhotobookFilter(df.FilterSet): 
    type = df.CharFilter(method='filter_type') 
    value = df.CharFilter(method='filter_value') 

    class Meta: 
     model = Article 

    def filter_type(self, queryset, name, value): 
     return queryset.filter(**{'attributes__type': value}) 

    def filter_value(self, queryset, name, value): 
     return queryset.filter(**{'attributes__value': value}) 

而现在像?type=brand&value=Nike查询应该工作。

很明显,你可以凝结两个条件成一个过滤器和例如硬编码的带状部分:

class PhotobookFilter(df.FilterSet): 
    brand = df.CharFilter(method='filter_brand') 

    def filter_brand(self, queryset, name, value): 
     return queryset.filter(**{'attributes__type': 'brand', 'attributes__value': value}) 

但让他们分开的感觉方式更加灵活。

+0

这不起作用,因为'Article'上没有字段叫'attribute'。它返回错误:'关系字段不支持嵌套查找。有一个名为'attributes'的字段,我需要使用此类型 - 值组合过滤至少存在一个属性的所有文章。 PS将两者分开会更加困难,因为我还需要在另一个类型 - 值组合上进行过滤,而在手头,我需要的类型是预定义的。 – physicalattraction

+1

好的,我没有在你的领域发现'related_name'。是的,如果你觉得这样,你可以很难编码过滤部分(见更新的例子)。如果不知道所有要求,很难猜测究竟有什么意义。祝你好运。 – arie

0

使用search_fields。对于正确的结果重命名“类型”属性名称http://www.codesend.com/view/09ca65d42248fe1d89d07ce151f4f050/

+0

搜索领域是非常方便的,如果该字段' type'和'value'将在我查询的模型中定义(在这种情况下为'Article'),但在这种特殊情况下,这些字段没有在'Article'中定义,而是在'Attribute'中定义,而I在模型“Article”中的字段'attributes'中有一个列表。 – physicalattraction

1

您还可以过滤相反这样的:

class PhotobookFilter(df.FilterSet): 
    brand = df.CharFilter(method='filter_brand') 

    class Meta: 
     model = Article 

    def filter_brand(self, queryset, name, value): 
     articles = Attribute.objects.filter(type="brand", value=value).values_list('article_id', flat=True) 
     return queryset.filter(id__in=articles) 

这将创建一个子查询Attribute,这将仍然是在最后一个SQL请求