Как правильно отфильтровать через связанное поле ManyToMany с помощью django-filters?
Есть модель Book и Category. Они связаны через поле category в модели Book.
При фильтрации с помощью django-filters по полю `categories` выдает все записи. Я делаю что-то не так, но не знаю что.
models.py
from django.db import models class Category(models.Model): title = models.TextField() class Book(models.Model): title = models.TextField() isbn = models.TextField(null=True, blank=True) pagecount = models.IntegerField(null=True, blank=True) publisheddate = models.TextField(null=True, blank=True) thumbnailurl = models.TextField(null=True, blank=True) shortdescription = models.TextField(null=True, blank=True) longdescription = models.TextField(null=True, blank=True) status = models.TextField() authors = models.JSONField() categories = models.ManyToManyField( Category, blank=True ) |
from django.db import models class Category(models.Model): title = models.TextField() class Book(models.Model): title = models.TextField() isbn = models.TextField(null=True, blank=True) pagecount = models.IntegerField(null=True, blank=True) publisheddate = models.TextField(null=True, blank=True) thumbnailurl = models.TextField(null=True, blank=True) shortdescription = models.TextField(null=True, blank=True) longdescription = models.TextField(null=True, blank=True) status = models.TextField() authors = models.JSONField() categories = models.ManyToManyField( Category, blank=True )
views.py
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.generics import CreateAPIView, ListAPIView from django_filters.rest_framework import DjangoFilterBackend from api.models import Book, Category, FeedBack from api.serializers import BookSerializer, CategorySerializer, FeedBackSerializer from api.filters import BookFilter class ListRetrieveBook(ReadOnlyModelViewSet): """ Получение всех книг, книг по категории, конкретной книги. """ queryset = Book.objects.all() serializer_class = BookSerializer filter_backends = (DjangoFilterBackend,) filterset_fields = ('categories__title',) |
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.generics import CreateAPIView, ListAPIView from django_filters.rest_framework import DjangoFilterBackend from api.models import Book, Category, FeedBack from api.serializers import BookSerializer, CategorySerializer, FeedBackSerializer from api.filters import BookFilter class ListRetrieveBook(ReadOnlyModelViewSet): """ Получение всех книг, книг по категории, конкретной книги. """ queryset = Book.objects.all() serializer_class = BookSerializer filter_backends = (DjangoFilterBackend,) filterset_fields = ('categories__title',)
В общем, если делаю фильтрацию по id: filterset_fields = ('categories',), то фильтрует норм, а если filterset_fields = ('categories__title',), то просто возвращает все записи.
Дополнительно:
Я допустил, ошибку, неправильно делая запрос:
http://127.0.0.1:8000/api/v1/books?categories=<Название категории> |
http://127.0.0.1:8000/api/v1/books?categories=<Название категории>
Сработал запрос вида:
http://127.0.0.1:8000/api/v1/books?categories__title=<Название категории> |
http://127.0.0.1:8000/api/v1/books?categories__title=<Название категории>
Может кому то поможет..
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для правильного фильтрования через связанное поле ManyToMany с помощью django-filters, необходимо создать собственный фильтр, который будет учитывать связанные объекты.
Для начала, убедитесь, что у вас есть модель с полем ManyToMany, которое вы хотите фильтровать, и что у вас установлен django-filters.
Затем создайте новый файл filters.py в вашем приложении и импортируйте необходимые модули:
from django_filters import FilterSet, ModelMultipleChoiceFilter from .models import YourModel
Создайте класс фильтра, который будет наследоваться от FilterSet и определите в нем поле ManyToMany, которое вы хотите фильтровать:
class YourModelFilter(FilterSet): field_name = ModelMultipleChoiceFilter(queryset=YourModel.objects.all())
Затем добавьте этот фильтр к вашему представлению, используя django-filters:
from django_filters.views import FilterView from .filters import YourModelFilter class YourModelListView(FilterView): model = YourModel filterset_class = YourModelFilter template_name = 'your_template.html'
Теперь вы можете использовать ваш фильтр в шаблоне вашего представления:
{{ filter.form }} <button type="submit">Filter</button> {% for object in filter.qs %} {{ object }} {% endfor %}{{ filter.form }} <button type="submit">Filter</button> {% for object in filter.qs %} {{ object }} {% endfor %}
Теперь у вас должен быть рабочий фильтр ManyToMany, который позволяет пользователям фильтровать объекты по связанным полям. Не забудьте провести тестирование, чтобы убедиться, что фильтр работает корректно.