You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中将header函数改造为视图装饰器?

改造方案

首先先修正你原代码里的两处语法错误和可能的逻辑问题:

  1. header函数里的.first())多了一个右括号,应改为.first();
  2. 你用values("nickname")取balance,这明显是笔误,应改为values("balance");
  3. 原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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:15:47