我可以通过 django 视图访问装饰器中的上下文对象吗
Posted
技术标签:
【中文标题】我可以通过 django 视图访问装饰器中的上下文对象吗【英文标题】:Can I access context object in decorator over django view 【发布时间】:2021-01-04 12:10:12 【问题描述】:我有多个 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
【问题讨论】:
您希望通过向 HTTP 响应添加内容来获得什么优势或用途? 不更改具有return render(request, 'tmp.html')
的视图会很方便,而是向它们添加装饰器,因此它们的 HttpResponse 将具有我需要在模板中访问的上下文。最简单的方法是将foo()
放入每个函数并将每个返回更改为return render(request, 'tm.html', context)
"因此他们的 HttpResponse 将具有我需要在模板中访问的上下文" .... HttpResponse
是具有 "渲染输出"的东西,即render(request, 'some_template.html', context)
的结果。在这种情况下,您无法操纵上下文数据
此外,我建议您使用 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
【讨论】:
以上是关于我可以通过 django 视图访问装饰器中的上下文对象吗的主要内容,如果未能解决你的问题,请参考以下文章
Django:在其他装饰器中重用 login_required 装饰器