#python #django #python-2.7 #django-views #python-decorators
#python #django #python-2.7 #django-views #python-декораторы
Вопрос:
У меня есть несколько представлений django, к которым я хочу добавить некоторый контекст на основе их ответа и кода состояния. Прямо сейчас у меня есть код, который выглядит примерно так:
def my_decor(func):
def wrapper(*args, **kwargs):
response = func(*args, **kwargs)
if response.status_code == 200: # It will be changed to manipulate 2XX reponses only
new_data = foo()
response.context['some_new_data'] = new_data
return response
return wrapper
@my_decor
def view1(request):
# some logic
context = {'some_data': 'some_value'}
return render(request, 'some_template.html', context)
@my_decor
def view2(request):
# more logic
return render(request, 'another_template.html')
Итак, по сути, я хочу создать декоратор, который можно использовать с представлениями, которые прикрепляют контекст при возврате, и с теми, которые этого не делают.
Прямо сейчас я получаю AttributeError: 'HttpResponse' object has no attribute 'context'
.
Что я делаю не так?
Python 2.7.13 и Django 1.7.11
Комментарии:
1. Какое преимущество или использование вы хотите получить, добавив что-то в HTTP-ответ?
2. Будет удобно не изменять существующие представления
return render(request, 'tmp.html')
, а добавлять к ним декоратор, чтобы их HttpResponse имел контекст, к которому мне нужно получить доступ в шаблоне. Самым простым способом было бы ввестиfoo()
в каждую функцию и изменить каждый возврат наreturn render(request, 'tm.html', context)
3. «таким образом, их HttpResponse будет иметь контекст, к которому мне нужно получить доступ в шаблоне» …. Это то
HttpResponse
, что имеет «визуализированный вывод» , то есть результатrender(request, 'some_template.html', context)
. В этом случае вы не можете манипулировать данными контекста4. Более того, я бы рекомендовал использовать CBV, чтобы у вас было больше контроля над контекстными данными
Ответ №1:
После того, как вы вызовете func(*args, **kwargs)
свой декоратор, вы отрисовали шаблон, и менять шаблон уже слишком поздно.
Вы можете переключиться на TemplateResponse
, что позволяет изменять контекст перед отображением шаблона. Получите доступ к контексту, используя атрибут ответа context_data
.
from django.template.response import TemplateResponse
@my_decor
def view1(request):
# some logic
context = {'some_data': 'some_value'}
return TemplateResponse(request, 'some_template.html', context)
В вашем декораторе измените response.context
на response.context_data
:
if response.status_code == 200: # n.b. this is only for 200 responses, not 2XX as you say in your comment
new_data = foo()
response.context_data['some_new_data'] = new_data