如何在Django中将header函数改造为视图装饰器?
改造方案
首先先修正你原代码里的两处语法错误和可能的逻辑问题:
header函数里的.first())多了一个右括号,应改为.first();- 你用
values("nickname")取balance,这明显是笔误,应改为values("balance"); - 原
header函数缺少return语句,必须返回获取到的refferals和balance。
修正后的基础数据查询逻辑:
def get_header_data(request): user_id = request.user.id # 优化查询:一次获取两个字段,减少数据库请求次数 customer = Customer.objects.filter(name_id=user_id).values("refferals", "balance").first() return customer.get("refferals"), customer.get("balance")
下面提供两种贴合你需求的装饰器改造方案:
方案一:视图改动极小(仅替换render)
这个方案只需要把视图里的render换成TemplateResponse,加上装饰器后就能自动将header数据注入模板上下文,无需手动构造上下文。
装饰器代码
from django.template.response import TemplateResponse def header_decorator(view_func): def wrapper(request, *args, **kwargs): # 执行header数据查询 refferals, balance = get_header_data(request) # 调用原视图,获取TemplateResponse对象 response = view_func(request, *args, **kwargs) # 将header数据注入上下文 if isinstance(response, TemplateResponse): response.context_data.update({ 'refferals': refferals, 'balance': balance }) # 确保模板已渲染 if not response.is_rendered: response.render() return response return wrapper
使用装饰器的视图
@header_decorator def acc_profile(request): # 有自定义上下文时可以传入,比如:{'foo': 'bar'} return TemplateResponse(request, 'accounts/profile.html', {})
方案二:完全不用修改原有视图逻辑(仅加装饰器)
如果你不想替换render,可以用这个方案:装饰器先获取header数据,接管上下文构造和模板渲染,视图只需要返回模板名和自定义上下文(如果有的话)。
装饰器代码
from django.shortcuts import render def header_decorator(view_func): def wrapper(request, *args, **kwargs): # 获取header基础数据 refferals, balance = get_header_data(request) base_context = { 'refferals': refferals, 'balance': balance } # 调用视图,拿到模板名和自定义上下文 template_name, custom_context = view_func(request, *args, **kwargs) # 合并基础上下文和自定义上下文 base_context.update(custom_context or {}) # 统一渲染模板 return render(request, template_name, base_context) return wrapper
使用装饰器的视图
@header_decorator def acc_profile(request): # 有自定义上下文时返回(模板名,自定义上下文),无自定义数据则返回空字典 return 'accounts/profile.html', {}
补充说明
- 两种方案都避免了重复代码,所有需要header数据的视图只需要添加
@header_decorator装饰器即可; - 优化了数据库查询:将原来的两次
filter查询合并为一次,减少数据库IO开销; - 如果使用类视图,可以将装饰器通过
method_decorator加到类的dispatch方法上。
内容的提问来源于stack exchange,提问作者Fors1t
相关产品推荐
相关产品推荐

