Могу ли я как-то использовать 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()])