基于Django类的视图 - 意外的装饰器行为

时间:2012-04-04 14:21:28

标签: python django django-views decorator django-class-based-views

[编辑] 所以看起来我的代码工作正常,另一段代码+疲惫就是问题 [/编辑]。

我有一个装饰器,它可以检查几个必需的请求键。

def fields_required(*fields):
assert isinstance(fields, tuple), "Fields must be of type tuple."

def wrap_func(fn):

    def wrapper(cls, request, *args, **kwargs):
        print 'oh hi'
        missing_fields = []
        for field in fields:
            if not request.REQUEST.has_key(field):
                missing_fields.append(field)

        if len(missing_fields) > 0:
            #maybe do smth here
            return HttpResponseBadRequest()          

        return fn(cls, request, *args, **kwargs)
    return wrapper
return wrap_func

如果缺少其中一个字段,我希望HTTP 403 Bad Request状态代码,但装饰器永远不会执行该代码。

我的视图文件的基本表示:

class ViewA(View):

    @fields_required('name','api_key')
    def get(self, request, *args, **kwargs):
        # some logic

class ViewB(View):

    @fields_required('SHOULD_NEVER_SEE','THIS_STUFF')
    def get(self, request, *args, **kwargs):
        # some logic

在浏览器中打开ViewA时,控制台输出如下:

('name', 'api_key')
('SHOULD_NEVER_SEE','THIS_STUFF')

我无法理解为什么执行ViewB的装饰器,以及为什么我的控制台中没有'哦hi'。任何见解?

1 个答案:

答案 0 :(得分:1)

ViewB的装饰器是"执行"但不是因为您正在查看ViewA。这是因为Python在执行文件本身时会修饰该方法。例如,以下打印b即使func未被调用:

def deco(f):
    print 'b'
    def g():
        print 'c'
    return g

@deco
def func():
    print 'a'

关于'哦嗨'不打印;你可以尝试将装饰器添加到dispatch而不是get(例如,将以下内容添加到您的视图中):

@method_decorator(fields_required('SHOULD_NEVER_SEE','THIS_STUFF'))
def dispatch(self, *args, **kwargs):
    pass