Есть ли способ разбивать страницы на rawqueryset, используя встроенную разбивку на страницы django? , когда я бросаю его в список, он бросает мне ошибку ... TypeError: ожидаемая строка или объект Unicode, обнаружен NoneType. Есть ли способ обойти это?django pagination и RawQuerySet
ответ
мне удалось добиться этого с помощью следующего:
paginator = Paginator(files, 12)
paginator._count = len(list(files))
Код в django.core.paginator.py:
- проверяет, является ли для _count установить
- если нет, то пытается для запуска .count(), который не существует
- если нет, то пытается использовать простой len
LEN на raw_queryset не работает, но преобразование фактического объекта Paginator к списку работ найти для меня в Django 1.3
Вы можете установить кол атрибут вручную для объекта RawQuerySet:
items = Item.objects.raw("select * from appitem_item")
def items_count():
cursor = connection.cursor()
cursor.execute("select count(*) from appitem_item")
row = cursor.fetchone()
return row[0]
items.count = items_count
для @Rockallite
>>> class A():
... def b(self):
... print 'from b'
...
>>>
>>> (A()).b()
from b
>>> def c():
... print 'from c'
...
>>> a = A()
>>> a.b = c
>>> a.b()
from c
django.core.paginator.Paginator ищет метод 'count()'. Поэтому настройка свойства 'count' не работает. – Rockallite
Почему, вы его протестировали? Конечно, это взломать, но я использовал его. Я имею в виду, что в python вы можете заменить один метод другим. –
Rockallite, я добавил код, чтобы проиллюстрировать, как работает этот хак –
qs.filter(**pfilter).distinct().extra(select={'test': 'COALESCE(`psearch_program`.`eu_price`, 999999999)'}).extra(order_by=['test'])
-1: объясните, что делается, с чем совместимость и т. Д. –
Очевидно LEN (список (файлов)) очень неэффективна памяти для больших наборов исходных запросов. Если вы знаете запрос, который был запущен, вы можете запустить другой запрос с помощью COUNT (*) и назначить его для paginator._count, если количество результатов не будет изменяться между каждым запросом. В качестве альтернативы, у разных СУБД есть способы вложить общее количество строк в каждую строку запроса, если результаты запроса постоянно меняются. – Chris
К сожалению, [RawQuerySet .__ getitem__()] (https://code.djangoproject.com/browser/django/trunk/django/db/models/query.py?rev=17381#L1517) вызывает список (сам) в любом случае - поэтому он будет полностью загружен в память, как только вы назовете 'paginator.get_page()'. Чтобы этого избежать, я думаю, вам придется подклассировать RawQuerySet и убедиться, что ваш сырой SQL имеет LIMIT/OFFSET, и даже тогда вы потеряете кэш результатов обычного набора запросов, поэтому дважды обращайтесь к qs [0] дважды ударит БД. – AdamKG
Да, он ударит дважды. Я просто открыл для себя это тоже. Поэтому лучше всего писать ОЧЕНЬ эффективный sql для этого необработанного набора запросов и вместо передачи необработанного запроса на len (list()), а для paginator вы сначала оцениваете набор запросов, перебирая его. Подобно l = [item для элемента в наборе запросов], а затем передайте это l как для paginator, так и для len (l). Это дает вам только один вызов базы данных. –