Найти - Пользователи
Полная версия: Использовать результат запроса из первой функции вьюхи во второй функции этой же вьюхи.
Начало » Django » Использовать результат запроса из первой функции вьюхи во второй функции этой же вьюхи.
1
MikaMika
Привет.
Есть шаблон одного из приложений проекта (пусть будет app1).
{% extends 'base.html' %}
{% block content %}
<TABLE>
<TR>
<TD>{% block info1 %}{{ info1 }}{% endblock %}</TD>
<TD>{% block info2 %}{{ info2 }}{% endblock %}</TD>
</TR>
</TABLE>
{% endblock %}
Есть функция вьюхи, которая рендерит этот шаблон, а именно блок “info1”.
Ну например:
def inf1(request):
    info1 = Info1.objects.get(pk=1)
    return render(request, 'app1_base.html', {'info1': info1}
Ещё одна функция этой же вьюхи так же использует этот основной шаблон и рендерит контент в блок “info2”.
Ну например:
def inf2(request):
    info2 = Info2.objects.get(pk=1)
    return render(request, 'app1_base.html', {'info2': info2}
Но к сожалению при работе второй функции вьюхи, блок “info1” остаётся пустым, так - как рендерится в первой функции вьюхи приложения app1.
А мне нужно что бы он (блок “info1”) всегда был заполненный.
Как это сделать?
Я пока нашёл только один выход.
Это сделать одинаковые запросы во второй функции и передать результат в шаблон.
def inf2(request):
    info1 = Info1.objects.get(pk=1)
    info2 = Info2.objects.get(pk=1)
    return render(request, 'app1_base.html', {'info1': info1, 'info2': info2}
Как ещё можно сделать подобную вещь?






reclosedev
Можно написать свой context processor
https://docs.djangoproject.com/en/dev/ref/templates/api/#writing-your-own-context-processors
buddha
reclosedev
Можно написать свой context processorhttps://docs.djangoproject.com/en/dev/ref/templates/api/#writing-your-own-context-processors

Почему context processor? Я вот недавно столкнулся с подобным, на все страницы надо было одну форму выводить. Пришел к выводу, что этим занимается middleware. Ошибаюсь?

Посему советую создать свой промежуточный слой middleware, в котором будет обрабатываться ответ из каждой фунции и будет добавляться в него info2 = Info2.objects.get(pk=1). Но в таком случае нужно будет заменить все сокращения, типа render, render_to_response на SimpleTemplateResponse\TemplateResponse.
Либо запилить декоратор.
Либо оставить как есть, ведь способы описанные выше по своей сути то же самое.
reclosedev
buddha
Не совсем понял, что вы предлагаете (process_view? process_template_response?).
Если ТС нужны данные только в шаблоне, а не во вьюхах, context processor как раз подойдет. Кмк middleware для более низкоуровневых/сложных вещей.

buddha
Но в таком случае нужно будет заменить все сокращения, типа render, render_to_response на SimpleTemplateResponse\TemplateResponse.
Либо запилить декоратор.
Это почему?
buddha
Да, я имел ввиду process_template_response.

У объекта HttpResponse нету возможности(интерфейса) для добавления в контекст новых переменных(это я про render, render_to_response).
Standard HttpResponse objects are static structures. They are provided with a block of pre-rendered content at time of construction, and while that content can be modified, it isn’t in a form that makes it easy to perform modifications.

However, it can sometimes be beneficial to allow decorators or middleware to modify a response after it has been constructed by the view. For example, you may want to change the template that is used, or put additional data into the context.

TemplateResponse provides a way to do just that. Unlike basic HttpResponse objects, TemplateResponse objects retain the details of the template and context that was provided by the view to compute the response. The final output of the response is not computed until it is needed, later in the response process.
Я так понял, что SimpleTemplateResponse был создан чисто под эти ситуации , да и сам этот класс наследник HttpResponse. А TemplateResponse просто уже включает RequestContext. Проще в исходный код посмотреть…
reclosedev
А, да, шорткаты HttpResponse же возвращают в отличие от generic views.

Получается, если не используется TemplateResponse, то для добавления значения во все шаблоны проще использовать context processor.
svas
MikaMika
А мне нужно что бы он (блок “info1”) всегда был заполненный.

Я пока нашёл только один выход.
Это сделать одинаковые запросы во второй функции и передать результат в шаблон.
Если блок info1 должен быть заполнен только в inf2 проще просто передавать его в шаблон из inf2.
Если блок info1 должен быть заполнен вообще везде то есть 2 варианта:
1. Как советовали выше написать context processor.
2. Использовать class based views и написать миксин с переопределенным методом get_context_data и наследовать от него все вьюхи.
Первый вариант наверное лучше.

MikaMika
Сделал прослойку:
def return_info1():
    return info1 = Info1.objects.get(pk=1)
Эту функцию использую везде, где нужно:
def inf1(request):
    return render(request, 'app1_base.html', {'info1': return_info1()}
def inf2(request):
    info2 = Info2.objects.get(pk=1)
    return render(request, 'app1_base.html', {'info1': return_info1(), 'info2': info2}
Насколько я помню запросы в Django кэшируются, и это хорошо!
reclosedev
А если еще что-то во все шаблоны нужно будет добавить, будете править все view?

myapp/path/to/context_processor.py
def return_info1(request):
    return {'info1': Info1.objects.get(pk=1)}

settings.py
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
 
TEMPLATE_CONTEXT_PROCESSORS += (
    'myapp.path.to.context_processor.return_info1',
)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB