Bonky Zhu
If someone is able to show me that what I think or do is not right, I will happily change, for I seek the truth, by which no one was ever truly harmed. It is the person who continues in his self-deception and ignorance who is harmed.

Django学习之修饰器

Python中的修饰器

以下转自:https://baijiahao.baidu.com/s?id=1626911318049316751

在下图的代码中我们定义了getList( )函数,用来从10的8次方个自然数中随机挑选n个数并按照从小到大的顺序进行排序。如果我们想对getList( )函数的功能进行拓展(比如增加计时功能,计算函数耗时),最简单的实现方法是在原函数中添加代码,先后获取开始时间和结束时间,二者的差值即为函数的运行时间,下图中多行注释部分为添加的代码。

img

如果是个人程序,这样的解决方案无可厚非,但如果是集体开发的大型项目,这样的改动通常是不被允许的,如果大家都为了各自的需求在原函数中添加代码,很可能会造成灾难性的后果。还有一种解决方案,就是将原函数封装到一个新的函数中,在新函数中对原函数的运行时间进行计算(如下图)。

img

上图中使用getListTime( )函数对getList( )函数进行了封装,在getList( )函数执行前和结束后分别计时,然后求得函数耗时。这种方案不用修改原函数中的代码,看似可行,实际上存在很多的问题。使用该方案不仅需要为每一个需要功能拓展的函数分别新建一个新函数,而且还要修改所有的调用,如果需要功能拓展的函数有成百上千个,可想而知会带来多大的工作量。如何简洁优雅地实现函数的功能拓展呢?python中最佳方案是“装饰器”。

img

上图代码第5行至第11行定义了一个装饰器函数decorator( ),这个函数有三个特殊之处:一是使用函数对象作为参数;二是使用了内部函数(闭包)wrapper( )/code>;三是返回值是一个函数对象。其实这些并不难理解,python中万物皆为对象,当然可以像其它对象一样作为函数的参数和返回值。第13行用@语法对getList( )函数进行装饰,在第20行代码调用getList( )函数时,getList( )不会立即执行,而是被当作参数传入装饰器函数decorator( )中,然后在闭包wrapper中完成对getList( )的调用。

乍看之下使用装饰器与上面提到的函数封装似乎差别不大,仔细分析就会发现装饰器能显著提高开发效率。首先只需要在函数定义之前添加code>@语句就能对所有函数进行功能拓展,大大减少了代码测试、版本更新的工作量;其次丝毫不会影响对该函数的调用,即使该函数被调用了千万次,也不需要任何的修改;第三最大限度保持了代码的可读性和扩展性,如果需要为原函数增加新的功能,只需要在函数定义前加上一条code>@语句。

登录限制 login_required()

我们只需要在setting.py中设置登录页面的URL即可

settings.py
LOGIN_URL = '/login/'  #这个路径需要根据你网站的实际登陆地址来设置,也就是登录路由

再定义视图,视图前加上code>@login_requred

# views.py
from djanco.contrib.auth.decorators import login_required
@login_required             # 例子比较简单
def myview(request):
    return render_to_response('index.html')    # 假设其对应路由为/index/

自行指定login页面地址也是可以的

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...
Share

You may also like...

发表评论