Применять Django FilterSet к аннотированному QuerySet? - PullRequest
0 голосов
/ 29 июня 2018

Я пытаюсь применить фильтр к аннотированному набору запросов, как это сделано здесь: https://docs.djangoproject.com/en/2.0/topics/db/aggregation/#filtering-on-annotations

Аналогично приведенному ниже фрагменту, я бы хотел, чтобы highly_rated составлял FilterSet, который собирает параметры запроса

highly_rated = Count('books', filter=Q(books__rating__gte=7))
Author.objects.annotate(num_books=Count('books'), highly_rated_books=highly_rated)

Я бы хотел сделать этот highly_rated компонент FilterSet, который принимает запросы. Что-то вроде:

class MainFilter(FilterSet):
    class Meta:
        model = Author
        fields = {
            author: ['in', 'exact'],
            genre: ['in', 'exact']
        }

class AnnotatedFilter(FilterSet):
    class Meta:
        fields = {
            'books__rating': ['gt', 'lt' ],
        }

class MyView(ListApiView):
    filter_class = AuthorFilter

    def get_queryset(self):
        annotated_filter = AnnotatedFilter(request) # how do I set up another filter based on the request?
        Author.objects.annotate(num_books=Count('books'), FilterSet=annotated_filter) # how do I apply it to an annotated queryset?

Все, чтобы я мог запросить что-то вроде:

api/authors/?genre=Fantasy&books__rating__gt=5

Где один из параметров выполняется для всех записей, а другие параметры - для аннотированной части.

Любая помощь очень ценится. Спасибо!

1 Ответ

0 голосов
/ 29 июня 2018

Изменить get_queryset() метод на

def get_queryset(self):
    return Author.objects.annotate(num_books=Count('books')


и определите это поле в Filter class как

class AuthorFilter(FilterSet):
    num_books = filters.NumberFilter(name='num_books')
    class Meta:
        model = Author
        fields = ['num_books',]#other fields

затем используйте API как /api/end/point/authorlist/?num_books=10

Пример

models.py

from django.db import models


class Sample(models.Model):
    foo = models.IntegerField()
    bar = models.IntegerField()

views.py

from django.db.models import F
from django_filters import rest_framework as filters


class MySampleAPI(viewsets.ModelViewSet):
    filter_backends = (filters.DjangoFilterBackend,)
    filter_class = SampleFilterClass
    serializer_class = SampleSerializerClass

    def get_queryset(self):
        return Sample.objects.annotate(foo_bar_sum=F('foo') + F('bar'))

filters.py

from django_filters import rest_framework as filters


class SampleFilterClass(filters.FilterSet):
    sum = filters.NumberFilter(name='foo_bar_sum', lookup_expr='gte')

    class Meta:
        model = Sample
        fields = ['sum', ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...