Использование результатов запроса в ОБОИХ шаблонах и представлении
В Django мне нужно сделать запрос к таблице, чтобы получить некоторые данные из базы данных. Мне нужны результаты ОБА в представлениях и во ВСЕХ моих шаблонах.
Есть ли способ выполнить этот запрос только один раз?
Вот моя текущая установка, если я не использую контекстный процессор:
views.py:
def collect_important_information():
return SomeModel.objects.filter(parameter=abc)
def homepage(request):
information = collect_important_information()
if information:
do something
context = {"information": information}
return render(request, "index.html", context)
def second_page(request):
information = collect_important_information()
if information:
do something else
context = {"information": information}
return render(request, "second.html", context)
def third_page(request):
information = collect_important_information()
if not information:
do something
context = {"information": information}
return render(request, "third.html", context)
def fourth_page(request):
information = collect_important_information()
context = {"information": information}
return render(request, "third.html", context)
Здесь очень много повторений. Я могу сократить это, используя custom context_processor для вставки переменной "information" в каждый шаблон. Что-то вроде этого:
custom_context_processor.py:
def site(request):
return { "information": SomeModel.objects.filter(parameter=abc) }
Это позволяет мне сократить views.py до следующего:
def collect_important_information():
return SomeModel.objects.filter(parameter=abc)
def homepage(request):
information = collect_important_information()
if information:
do something
return render(request, "index.html")
def second_page(request):
information = collect_important_information()
if information:
do something else
return render(request, "second.html")
def third_page(request):
information = collect_important_information()
if not information:
do something
return render(request, "third.html")
def fourth_page(request):
return render(request, "fourth.html")
Мои представления намного чище. Однако, если я сделаю это, мне придется выполнять запрос к базе данных дважды для многих из этих запросов. Один раз для получения нужных мне переменных базы данных внутри моей функции views.py (для некоторого условия, которое происходит независимо от шаблона), а второй раз в файле контекстного процессора.
Есть ли способ как-то "централизовать" запрос, чтобы он выполнялся только один раз, и при этом вставить его в файл шаблона и иметь его доступным в функции представления?
Есть ли способ как-то "централизовать" запрос, чтобы он выполнялся только один раз, и при этом вставить его в файл шаблона и иметь его доступным в функции представления?
QuerySet являются ленивыми построение кверисета будет не делать запрос к базе данных, вы делаете запрос к базе данных, если вы потребили кверисет, например, перечисляя его, вызывая str(…), repr(…) и len(…) на нем, проверяя его истинность с помощью bool(…) или в предложении if/elif.
Если вы используете контекстный процессор, который передает отфильтрованный кверисет в шаблон, и вы do не используете кверисет описанным выше способом, это не сделает запрос. Более того, если данные будут переданы в контекст, они переопределят данные в контекстном процессоре. Поэтому вы можете добавить его в контекст в случае, если вы уже оценили его в представлении, чтобы предотвратить выполнение второго запроса к базе данных, вы таким образом переопределите его в контексте, так что не будет ссылки на "другой" queryset, и результат будет использован повторно.
Нужно быть осторожным, чтобы не создать новый запрос, если предыдущий уже оценен. Например, если qs является оцененным набором запросов, вы должны снова работать с qs, если вы работаете с qs.all(), это создаст новый QuerySet, который затем сделает запрос к базе данных.