2014-06-25 12 views
8

Chciałbym filtrować parametry zapytania w moim interfejsie API REST - see django docs on this. Jednak jeden parametr życzę filtrować jest dostępna tylko za pośrednictwem modelu @propertyUżywanie niestandardowych metod w filtrze z django-rest-framework

przykład models.py:

class Listing(models.Model): 
    product = models.OneToOneField(Product, related_name='listing') 
    ... 
    @property 
    def category(self): 
     return self.product.assets[0].category.name 

Oto konfiguracja mojego API listingu zgodnie z django-filter docs

class ListingFilter(django_filters.FilterSet): 
     product = django_filters.CharFilter(name='product__name') 
     category = django_filters.CharFilter(name='category') #DOES NOT WORK!! 

     class Meta: 
      model = Listing 
      fields = ['product','category'] 

    class ListingList(generics.ListCreateAPIView): 
     queryset = Listing.objects.all() 
     serializer_class = ListingSerializer 
     filter_class = ListingFilter 

Jak mogę odpowiednio filtrować według listing.category? Nie jest dostępny bezpośrednio w modelu aukcji.

+0

W takich przypadkach odpowiedź od innego pytanie może help: http://stackoverflow.com/questions/14258338/django-rest-framework-filtering/35506369#35506369 – iankit

Odpowiedz

13

Użyj parametru „działanie”, aby określić niestandardową metodę - see django-filter docs

najpierw zdefiniować metodę, która filtruje się queryset wykorzystując wartość parametru Kategoria:

def filter_category(queryset, value): 
     if not value: 
      return queryset 

     queryset = ...custom filtering on queryset using 'value'... 
     return queryset 

filtr Zamieszczone powinien wyglądać tak :

class ListingFilter(django_filters.FilterSet): 
     ... 
     category = django_filters.CharFilter(action=filter_category) 
     ... 
+4

Krótko mówiąc, "akcja" django została zastąpiona przez "metodę". http://django-filter.readthedocs.io/en/latest/migration.html –

-1

w trosce o prędkości bazy danych, należy po prostu dodać kategorię do modelu aukcji

class Listing(models.Model): 
    product = models.OneToOneField(Product, related_name='listing') 
    category = models.ForeignKey(Category) 

Następnie użyj post_save signal zachować pole aktualizowane

from django.dispatch import receiver 
from django.db.models.signals import post_save 

@receiver(post_save, sender=Product) 
def updateCategory(sender, instance, created, update_fields, **kwargs): 
    product = instance 
    product.listing.category = product.assets[0].category.name 
    product.listing.save() 

Następnie przefiltrować przez jego nazwę tak samo, jak każda inna dziedzina:

class ListingFilter(django_filters.FilterSet): 
    ... 
    category = django_filters.CharFilter(name='category__name') 
    ...