【发布时间】:2015-01-22 09:54:47
【问题描述】:
我有一个类A 和方法do_something(self,a,b,c) 和另一个实例方法验证输入并检查名为can_do_something(self,a,b,c) 的权限。
这是我代码中的常见模式,我想编写一个接受验证函数名称并执行测试的装饰器。
def validate_input(validation_fn_name):
def validation_decorator(func):
def validate_input_action(self,*args):
error = getattr(self,validation_fn_name)(*args)
if not error == True:
raise error
else:
return func(*args)
return validate_input_action
return validation_decorator
调用函数如下
@validate_input('can_do_something')
def do_something(self,a,b,c):
return a + b + c
问题是我不确定如何通过验证功能维护self。我已将验证 fn 名称与 getattr 一起使用,因此 fn 可以在实例的上下文中运行,但我无法为 func(*args) 执行此操作。
那么实现这一目标的正确方法是什么?
谢谢。
编辑
所以按照@André Laszlo 的回答,我意识到 self 只是第一个参数,所以根本不需要使用getattr,只需传递*args。
def validate_input(validation_fn):
def validation_decorator(func):
def validate_input_action(*args):
error = validation_fn(*args)
if not error == True:
raise error
else:
return func(*args)
return validate_input_action
return validation_decorator
更优雅,它也支持静态方法。
向@André Laszlo 示例添加静态方法证明装饰器正在工作:
class Foo(object):
@staticmethod
def validate_baz(a,b,c):
if a > b:
return ValueError('a gt b')
@staticmethod
@validate_input(Foo.validate_baz)
def baz(a,b,c):
print a,b,c
>>> Foo.baz(1,2,3)
1 2 3
>>> Foo.baz(2,1,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in validate_input_action
ValueError: a gt b
但是,当我尝试在 django 模型中做同样的事情时:
from django.db import models
from django.conf import settings
settings.configure()
class Dummy(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=10)
def can_say_name(self):
if name is None:
return Exception('Does not have a name')
@validate_input(can_say_name)
def say_name(self):
print self.name
@staticmethod
def can_create_dummy(name):
if name == 'noname':
return Exception('No name is not a name !')
@staticmethod
@validate_input(Dummy.can_create_dummy)
def create_dummy(name):
return Dummy.objects.create(name=name)
我得到以下信息:
NameError: name 'Dummy' is not defined
那么在这个问题上,django 模型和对象有什么不同呢?
【问题讨论】:
-
我猜你写了很多 js 代码? :)
-
我猜。为什么要问?
-
只是觉得我认出了一个模式。有趣的问题。