在 Django 的 View 中利用 function decorator 可实现一定程度的代码重用

本文介绍了一种在Django框架中对多个相似视图进行重构的方法,通过使用装饰器来减少代码重复并提高可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在 Django 中,假设有几个 view, 他们都接受类似的参数,做类似的处理,最后又输出类似的变量到模板中配合显示,唯一不同的就是模板路径。

最普通的写法可能是这样:

def view_a(request, some_id):
    some_obj 
= SomeClass.objects.get(pk=some_id)
    
# 一些处理
    # 
    return render_to_response("a.html", {'some_obj': some_obj},
        context_instance
=RequestContext(request))

def view_b(request, some_id):
    some_obj 
= SomeClass.objects.get(pk=some_id)
    
# 一些处理
    # 
    return render_to_response("b.html", {'some_obj': some_obj},
        context_instance
=RequestContext(request))

def view_c(request, some_id):
    some_obj 
= SomeClass.objects.get(pk=some_id)
    
# 一些处理
    # 
    return render_to_response("c.html", {'some_obj': some_obj},
        context_instance
=RequestContext(request))

这里显然很多代码重复,最容易想到的是把同样的代码取出来放到一个函数里,重构后代码变成了这样:

def some_logic(request, some_id, template_path):
    some_obj 
= SomeClass.objects.get(pk=some_id)
    
# 一些处理
    # 
    return render_to_response(template_path, {'some_obj': some_obj},
        context_instance
=RequestContext(request))

def view_a(request, some_id):
    some_logic(request, some_id, 
"a.html")

def view_b(request, some_id):
    some_logic(request, some_id, 
"b.html")

def view_c(request, some_id):
    some_logic(request, some_id, 
"c.html")

好多了,可是我们注意到传递进 view 的一些参数(这里只有一个 some_id)仍然重复的写了很多次。有没有更好的办法呢?有的,用 function decorator,可以写成这样:

def foo_view(template_path):
    
def my_decorator(f):
        
def new_f(request, some_id, *args, **kwds):
            some_obj 
= SomeClass.objects.get(pk=some_id)
            
# 一些处理
            # 
            return render_to_response(template_path, {'some_obj': some_obj},
                context_instance
=RequestContext(request))
        new_f.func_name 
= f.func_name
        
return new_f
    
return my_decorator
            
@foo_view(
"a.html")
def view_a(request, some_id):
    
pass

@foo_view(
"b.html")
def view_b(request, some_id):
    
pass

@foo_view(
"c.html")    
def view_c(request, some_id):
    
pass

这样具体的 view 里面什么代码也没写,仅仅向 decorator 传递了一个模板名称的参数就搞定了。具体的实现,被封装到了 foo_view 这个 decorator 的内部函数里面。decorator 的作用看上去类似于 C# 的 Attribute, 但实际上强大很多,Attribute 仅仅相当于一个简单的元数据,具体实现还需要在其他类里面去分离实现,并且查找理解起来也不太方便,尤其在阅读大型类库的时候。而 python 里的 decorator 可以对函数做任意的修改,可任意添加前置(pre),后置(post) 操作,甚至完全取代掉原来的函数。可以辅助做参数、返回值类型检测、AOP (用的比较多的有日志、异常处理等)等功能,十分强大和灵活。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值