as_view()(用于基于类的视图)能否在装饰器中实现?

1 投票
1 回答
677 浏览
提问于 2025-04-16 23:44

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 这种写法简单明了,所以我个人更喜欢这样。

撰写回答