as_view()(用于基于类的视图)能否在装饰器中实现?
Django中的as_view()用法让我有点困扰。简单来说,我厌倦了每次都要写my_view = MyView.as_view(),每个基于类的视图都得这样做(或者在每个使用基于类视图的url配置中都写as_view())。我觉得用一个类装饰器来实现这个功能会更简洁,所以我在想怎么做到这一点,既为了自己的代码,也为了能分享给其他人,看看有没有人感兴趣。所以我的问题是:有没有什么合理的方法可以实现一个“as_view”装饰器,这样下面的代码就能正常工作?
@as_view(my_view)
class MyView(View):
pass
这基本上等同于:
class MyView(View):
pass
my_view = MyView.as_view()
谢谢,这也帮助我学习Python的一些高级特性(比如装饰器)。
Ben
1 个回答
1
有一种方法可以考虑,就是让类装饰器去给某个对象设置属性,这个对象会包含你想定义的所有 as_views
。然后你可以在你的 urls.py 文件中使用这个对象。
import re
class Views(object):
"""Empty object for holding as_view method"""
views = Views()
def convert_name(name):
"""convert CapWords into cap_words"""
return name[0].lower() + re.sub(r'([A-Z])', lambda m:"_" + m.group(0).lower(), name[1:])
def as_view(views):
"""Adds decorated class-based views' as_view methods to views container"""
def decorator(cls):
name = convert_name(cls.__name__)
setattr(views, name, cls.as_view)
return cls
return decorator
接着在你的 views.py 文件中,你可以这样使用它:
from as_view_decorator import views, as_view
@as_view(views)
class MyView(View):
....
这样 MyView.as_view
就会被存储在 views
对象里,变成 views.my_view
。
你也可以在你的 views.py 文件中做类似的事情:
from as_view_decorator impor as_view
import sys; mod = sys.modules[__name__]
@as_view(mod)
class MyView(View):
...
这样就会把 my_view
设置为你 views
模块的一个属性。然后在你的 urls.py
文件中,你可以这样使用:
from app.views import my_view
urlpatterns = patterns('',
url(r'^$', my_view()),
)
我觉得 my_view = MyView.as_view
这种写法简单明了,所以我个人更喜欢这样。