如何编写基于类的Django验证器?

2024-09-28 05:27:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我用的是django1.8。在

documentation on writing validators有一个基于函数的验证器示例。它还说明了使用类的以下内容:

You can also use a class with a __call__() method for more complex or configurable validators. RegexValidator, for example, uses this technique. If a class-based validator is used in the validators model field option, you should make sure it is serializable by the migration framework by adding deconstruct() and __eq__() methods.

  • 基于类与基于函数的验证器的优缺点是什么?在
  • __call__()用于什么,它是如何使用的?在
  • deconstruct()用于什么,它是如何使用的?在
  • __eq__()用于什么,以及如何使用它?在

举个例子会很有帮助。完整的答案也可能值得提交到正式文件中。在

谢谢!在


Tags: the函数you示例forbyison
3条回答

除了一些基于类的复杂度验证程序之外,几乎没有从类开始实现的缺点。在

但也有一些优点:yon可以在类实例中保存一些内容以备将来验证,因此它不会在每次验证时都进行计算,例如编译的regex模式。您还可以通过将代码传播到类中的其他方法来创建更复杂的验证器。在

另外,您可以用一些参数构造验证器,这些参数可以在以后的验证过程中使用。在

__call__方法是实际的验证函数-它将像具有相同参数的普通验证函数一样被调用(以及附加的self参数-类的实例,就像在所有方法中一样)。它不是来自django框架,而是来自python本身。如果实现了__call__方法,任何类都可以像函数一样被调用。deconstruct方法在migration serializing中解释。__eq__也是来自python本身的,每个类都可以有,它只需比较两个对象来检查它们是否相等。在

验证器函数的一大优点是它们非常简单。它们只需将一个值作为参数,检查它是否有效,如果无效则引发ValidationError。您不需要担心deconstruct__eq__方法来进行迁移。在

文档中的validate_even示例比验证器类简单得多。在

def validate_even(value):
    if value % 2 != 0:
        raise ValidationError('%s is not an even number' % value)

如果您还需要检查其他数字的可除性,那么创建一个验证器类ValidateDivisibleBy。然后可以使用ValidateDivisibleBy(2)ValidateDivisibleBy(3)等等。但很多时候,验证器函数就足够了。在

除了能够从BaseValidator继承之外,选择基于函数的验证器与基于类的验证器可能不一定有明显的利弊。我更喜欢基于类的,因为您可以在必要时保持内部状态,而不必让客户端看到它(例如编译的正则表达式、表中的预计算值、历史记录等)

__call__方法使一个对象可调用,并允许它模拟类似函数的行为(例如,可以像函数一样调用对象),并且将调用对象的__call__重写。它要求您在验证器中实现特殊的__call__(self, ...)方法。在

class Callable(object):
    def __call__(self,*args,**kwargs):
        print('Calling', args, kwargs)

>>> c = Callable()
>>> c(2, 3, color='red')
Calling (2, 3) {'color': 'red'}
>>>

deconstruct方法似乎提供了一个点,客户机(即您)可以通过编写自定义实现来覆盖序列化行为。例如,请参见here。这似乎与clean方法类似,在该方法中,您可以为模型实现自定义的输入卫生,并在调用full_clean时自动调用(例如,当表单使用is_valid)时)。在

__eq__允许您在两个本身不可比较的对象之间实现比较。例如,如果您有

^{pr2}$

您的__eq__实现可以如下所示检查两个向量对象之间是否相等:

^{3}$

这样,就避免了对底层引用的浅层比较。在

相关问题 更多 >

    热门问题