Использование пользовательских методов в фильтре с django-rest-framework
Я хотел бы отфильтровать параметры запроса в моем REST API -см. документы django на этом. Однако один параметр, который я хочу фильтровать, доступен только через model @property
пример models.py:
class Listing(models.Model):
product = models.OneToOneField(Product, related_name='listing')
...
@property
def category(self):
return self.product.assets[0].category.name
вот настройка для моего API листинга в соответствии с 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
Как я могу соответствующим образом фильтровать по списку.категория? Он не доступен непосредственно в модели листинга.
2 ответов
используйте параметр 'action', чтобы указать пользовательский метод -см. django-filter docs
сначала определите метод, который фильтрует набор запросов, используя значение параметра category:
def filter_category(queryset, value):
if not value:
return queryset
queryset = ...custom filtering on queryset using 'value'...
return queryset
фильтр список должен выглядеть так:
class ListingFilter(django_filters.FilterSet):
...
category = django_filters.CharFilter(action=filter_category)
...
ради скорости базы данных, вы должны просто добавить категорию в каталоге модель
class Listing(models.Model):
product = models.OneToOneField(Product, related_name='listing')
category = models.ForeignKey(Category)
затем использовать post_save сигнал для обновления поля
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()
затем фильтровать по его имени, как и любое другое поле:
class ListingFilter(django_filters.FilterSet):
...
category = django_filters.CharFilter(name='category__name')
...