#python #django #django-models #django-views #django-queryset
#python #django #django-модели #django-просмотры #django-queryset
Вопрос:
В моем приложении django есть несколько разных способов получить объект набора запросов той же модели.
Я хотел бы использовать одну функцию для отображения данных — и это работало нормально, пока я не решил добавить как самое раннее, так и самое позднее время для отображения в верхней части списка.
Вот моя последняя попытка:
def render_list(request, objList):
latest = earliest = None
if objList:
latest = objList.latest('time').time
earliest = objList.earliest('time').time
context = {'objList': objList,
'earliest': earliest,
'latest': latest,
}
return render(request, 'list.html', context)
При этом выдается сообщение об ошибке:
TypeError: Cannot reverse a query once a slice has been taken.
Есть ли способ обойти эту проблему?
Подробнее: Функция render_list
вызывается несколькими функциями просмотра в views.py
, например :
def list_all(request):
objList = MyTable.objects.order_by('ip')
return render_list(request,objList)
def detail(request, ip, group):
objList = MyTable.objects
try:
item = MyTable.objects.get(ip=ip)
# display the details page...
except MyTable.DoesNotExist:
objList = MyTable.objects.complex_filter(...)
# more code
# ...
return render_list(request, objList)
и соответствующие строки в urls.py
path('list', views.list_all)
path('<group>/<ip>', views.detail)
Комментарии:
1. Что
objList
здесь? И это похоже на функцию просмотра (поскольку вызывается ее первый аргументrequest
, и он возвращает отображаемый шаблон) — как вы передаете то, что кажется сложным объектом (не простой строкой или числом) как часть URL?2. это функция, которая вызывается несколькими функциями просмотра
Ответ №1:
Способ обойти эту ошибку — использовать latest()
и earliest()
(а также first()
и last()
только для наборов запросов, которые не были нарезаны (например, с помощью queryset[:5]
для получения пяти лучших записей). objList
Похоже, что вы были нарезаны до того, как оно было передано функции.
Если у вас есть набор запросов, в котором записи расположены в правильном порядке (что означает, что самые ранние и последние являются первыми и последними), у вас есть еще два варианта:
- Используйте три дополнительных запроса, чтобы получить первую и последнюю запись:
earliest = objList[0]
latest = objList[objList.count()]
- Создайте экземпляры объектов в наборе запросов (вызов
len
этого делает). Затем вы можете получить доступ к первому и последнему элементу без дополнительных запросов:
latest = objList[len(objList)-1]
earliest = objList[0]
Для этого требуется только один запрос, но он загружает все объекты в наборе запросов в память.
Повторяю, это работает только в том случае, если набор запросов упорядочен так, чтобы иметь earliest
и latest
первый и последний. В противном случае вам придется определять отдельные наборы запросов.
Комментарии:
1. Некоторые функции просмотра, которые вызывают
render_list
фрагмент набора запросов, и порядок отличается…2. Я выяснил, что могу передать дополнительные аргументы
render_list
и выполнить там любую необходимую нарезку. Спасибо!