2013-01-10 82 views
2

我要过滤与多个查询多个字段是这样的:Django的REST框架 - 过滤

api/listings/?subburb=Subburb1, Subburb2&property_type=House,Apartment,Townhouse,Farm .. etc 

是否有任何内置的方式,我看了一下Django的过滤器,但它似乎是有限的,我想我会必须在我的api视图中手动执行此操作,但它变得混乱,过滤器上的过滤器

回答

2

过滤器上的过滤器并不杂乱,它被称为chained filters。因为有时存在将是property_type一段时间没有

而且链过滤器是必要的:

if property_type: 
    qs = qs.filter(property_type=property_type) 

如果你正在考虑那里将是多个查询则不是,它会在一个查询,因为仍然执行queryset是懒惰的。

或者你可以建立一个字典,并通过它只是一个时间:

d = {'property_type:': property_type, 'subburb': subburb} 
qs = MyModel.objects.filter(**d) 
+1

但对于像房产类型=房子多部分,联排别墅 – Harry

+0

我想将它们全部在查询中,所以每个子过滤器或过滤器都是。 – Harry

+0

好吧,我有它,像这样Foo.objects.filter(name__in = [“This”,“That”,“那些”)) – Harry

1

复杂的过滤器不出来的DRF甚至通过Django的过滤器插件支持的盒子。对于简单的情况下,你可以定义自己的get_queryset方法

这是直接从文档

def get_queryset(self): 
    queryset = Purchase.objects.all() 
    username = self.request.query_params.get('username', None) 
    if username is not None: 
     queryset = queryset.filter(purchaser__username=username) 
    return queryset 

然而,如果你支持多个过滤器,甚至他们中的一些复杂的这很快就会变得杂乱。

解决方案是定义一个自定义filterBackend类和ViewSet混合。这个mixin告诉视图如何理解一个典型的过滤器后端,这个后端可以理解所有明确定义的非常复杂的过滤器,包括何时应用这些过滤器的规则。

的样品过滤器后端是这样的(我在复杂性增大的顺序上定义不同的查询参数三个不同的过滤器:上ORM查找

class SomeFiltersBackend(FiltersBackendBase): 
    """ 
    Filter backend class to compliment GenericFilterMixin from utils/mixin. 
    """ 
    mapping = {'owner': 'filter_by_owner', 
       'catness': 'filter_by_catness', 
       'context': 'filter_by_context'} 
    def rule(self): 
     return resolve(self.request.path_info).url_name == 'pet-owners-list' 

直向前滤波器

def filter_by_catness(self, value): 
     """ 
     A simple filter to display owners of pets with high catness, canines excuse. 
     """ 
     catness = self.request.query_params.get('catness') 
     return Q(owner__pet__catness__gt=catness) 

    def filter_by_owner(self, value): 
     if value == 'me': 
      return Q(owner=self.request.user.profile) 
     elif value.isdigit(): 
      try: 
       profile = PetOwnerProfile.objects.get(user__id=value) 
      except PetOwnerProfile.DoesNotExist: 
       raise ValidationError('Owner does not exist') 
      return Q(owner=profile) 
     else: 
      raise ValidationError('Wrong filter applied with owner') 

更复杂的过滤器:

def filter_by_context(self, value): 
    """ 
    value = {"context_type" : "context_id or context_ids separated by comma"} 
    """ 
    import json 
    try: 
     context = json.loads(value) 
    except json.JSONDecodeError as e: 
     raise ValidationError(e) 

    context_type, context_ids = context.items() 
    context_ids = [int(i) for i in context_ids] 
    if context_type == 'default': 
     ids = context_ids 
    else: 
     ids = Context.get_ids_by_unsupported_contexts(context_type, context_ids) 
    else: 
     raise ValidationError('Wrong context type found') 
    return Q(context_id__in=ids) 

要充分理解如何是的作品,你可以阅读我的详细博文:http://iank.it/pluggable-filters-for-django-rest-framework/

所有的代码有一个要点,以及:https://gist.github.com/ankitml/fc8f4cf30ff40e19eae6