Могу ли я как-то использовать objs = Model.objects.raw(sql) с PageNumberPagination в django rest framework без передачи list(objs) в pagination?

В настоящее время я столкнулся с проблемой пагинации при использовании необработанных SQL-запросов в Django. Ситуация возникла, когда мне понадобилось применить дополнительный фильтр в LEFT OUTER JOIN моего запроса, который, как я обнаружил, не поддерживается напрямую ORM Django. Несмотря на попытку использовать FilteredRelation, я понял, что он не полностью отвечает моим требованиям.

В качестве обходного пути я решил использовать необработанные SQL-запросы, что позволило мне добиться желаемого фильтра. Однако при попытке постраничной сортировки результатов я столкнулся с препятствием. Похоже, что сырые наборы запросов не поддерживают пагинацию из коробки.

Вот фрагмент соответствующего кода:

queryset = CheckTraModelTotal.objects.raw(sql_query)
page = RawQuerySetPaginator(queryset, 15)
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)

Думаю, вам просто нужно изменить способ вызова пагинации, если ваш пример кода точен: page = RawQuerySetPaginator(queryset, 15)

Пагинация не должна иметь проблем с большинством необработанных запросов. Упорядочивание и поиск, конечно, являются проблемой.

class MyPagination(PageNumberPagination):
    page_size = 1

qs = User.objects.raw("select email from user order by id desc")

paginator = MyPagination()

# page is a list of user objects here
page = paginator.paginate_queryset(qs, request=req)

# generate the list of dict objects for output
serialized_data = UserSerializer(page, many=True).data

# create a Response(), with the `count` and next/prev links
output = paginator.get_paginated_response(serialized_data)

Пагинаторы запутаны, поскольку они внутренне используют пагинатор django, и, таким образом, имеют страницу, которая имеет пагинатор, который делает .count. Как он это делает, я не знаю, это магия. У RawQuerySet нет метода count(), но это все равно как-то работает.

print(f"total records => {paginator.page.paginator.count}")

Возможно, это поможет вам в тестировании, поэтому вот фрагмент, который я использую для генерации фальшивых запросов - вы не можете просто использовать вывод APIRequestFactory напрямую.

def make_request():
    from rest_framework.test import APIRequestFactory
    from rest_framework.request import Request
    from rest_framework.parsers import JSONParser
    req = APIRequestFactory().get("/", {"page": "1"})
    return Request(req, parsers=[JSONParser()])
Вернуться на верх