【问题标题】:How do I write a Class-Based Django Validator?如何编写基于类的 Django 验证器?
【发布时间】:2015-11-15 07:41:48
【问题描述】:

我正在使用 Django 1.8。

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

您还可以将具有__call__() 方法的类用于更复杂或可配置的验证器。例如,RegexValidator 就使用了这种技术。如果在验证器模型字段选项中使用基于类的验证器,则应通过添加 deconstruct()__eq__() 方法确保迁移框架可序列化它。

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

举个例子会很有帮助。完整的答案也可能值得提交到官方文档中。

谢谢!

【问题讨论】:

  • 记得采纳对你最有帮助的答案。

标签: python django validation class oop


【解决方案1】:

从头开始,几乎没有缺点 - 除了在实现基于类的验证器方面可能有些复杂。

但是有一些优点:你可以在类实例中保存一些东西以供将来验证,所以每次验证某些东西时都不会计算它,例如编译的正则表达式模式。您还可以通过将代码传播到类中的其他方法来创建更复杂的验证器。

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

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

【讨论】:

    【解决方案2】:

    除了能够从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__ 允许您在两个本身不可比较的对象之间进行比较。例如,如果您有一个

    class Vector2:
        def __init__(self, x, y):
            self.x = x
            self.y = y
    

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

    # ...
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    

    这样,您可以避免对底层引用进行浅显的比较。

    【讨论】:

      【解决方案3】:

      验证器函数的一大优点是它们非常简单。他们只是将一个值作为参数,检查它是否有效,如果不是,则引发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) 等等。但很多时候,验证器功能就足够了。

      【讨论】:

        猜你喜欢
        • 2020-08-25
        • 1970-01-01
        • 2015-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-08
        • 2015-07-10
        相关资源
        最近更新 更多