Как получить последнюю и самую раннюю версию из набора запросов django

#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 Похоже, что вы были нарезаны до того, как оно было передано функции.

Если у вас есть набор запросов, в котором записи расположены в правильном порядке (что означает, что самые ранние и последние являются первыми и последними), у вас есть еще два варианта:

  1. Используйте три дополнительных запроса, чтобы получить первую и последнюю запись:
 earliest = objList[0]
latest = objList[objList.count()]
  
  1. Создайте экземпляры объектов в наборе запросов (вызов len этого делает). Затем вы можете получить доступ к первому и последнему элементу без дополнительных запросов:
 latest = objList[len(objList)-1]
earliest = objList[0]
  

Для этого требуется только один запрос, но он загружает все объекты в наборе запросов в память.

Повторяю, это работает только в том случае, если набор запросов упорядочен так, чтобы иметь earliest и latest первый и последний. В противном случае вам придется определять отдельные наборы запросов.

Комментарии:

1. Некоторые функции просмотра, которые вызывают render_list фрагмент набора запросов, и порядок отличается…

2. Я выяснил, что могу передать дополнительные аргументы render_list и выполнить там любую необходимую нарезку. Спасибо!