2013-01-10 3 views
2

Je veux filtrer plusieurs champs avec plusieurs requêtes comme ceci:Django REST Framework - Filtrage

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

Y at-il construit de façon, je regardais les filtres django, mais il semble limité, et je pense que je le ferais dois le faire manuellement dans ma vue de l'api, mais son désordre, filtrant sur les filtres sur les filtres

Répondre

2

Filtrer sur les filtres sur les filtres n'est pas en désordre, il est appelé chained filters.

et les filtres à chaîne sont nécessaires parce que parfois il va être property_type quelque temps pas:

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

Si vous pensez qu'il va y avoir plusieurs requêtes alors non, il sera toujours exécuté dans une requête parce que Queryset sont paresseux.

Sinon, vous pouvez construire une dict et passez juste une fois:

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

Mais qu'en est multiple partie comme property_type = maison, maison – Harry

+0

Je veux avoir tous dans la requête, de sorte que chaque subburb ou quel que soit le filtre est. – Harry

+0

Ok je l'ai, comme ce Foo.objects.filter (name__in = ["Ceci", "That", "Ceux"]) – Harry

1

filtres complexes ne sont pas hors de la boîte supportée par DRF ou même par plug-in django-filtre. Pour les cas simples, vous pouvez définir votre propre méthode de get_queryset

Ceci est directement à partir de la documentation

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 

Cependant, cela peut rapidement devenir malpropre si vous êtes pris en charge plusieurs filtres et même certains d'entre eux complexe.

La solution consiste à définir une classe filterBackend personnalisée et un ViewSet Mixin. Ce mélange indique au viewet comment comprendre un backend de filtre typique et ce backend peut comprendre des filtres très complexes, tous explicitement définis, y compris des règles quand ces filtres doivent être appliqués.

Une base de filtre échantillon est comme ça (je l'ai défini trois filtres différents sur différents paramètres de la requête dans l'ordre croissant de complexité.

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' 

filtre avant tout droit lookups ORM

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') 

Filtres plus complexes:

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) 

Pour comprendre pleinement comment IS, il fonctionne, vous pouvez lire mon blogpost détaillée: http://iank.it/pluggable-filters-for-django-rest-framework/

Tout le code est là dans un Gist ainsi: https://gist.github.com/ankitml/fc8f4cf30ff40e19eae6

Questions connexes