我正在尝试设计一个验证表单字段的方案。我已经决定你可以将验证器列表传递到每个字段,例如
Field(validators=[email_validator, required_validator])
但后来我想,如果你想要or
验证器,而不是and
它们怎么办?例如,一个接受加拿大邮政编码,或美国邮政编码的字段。当然,我可以创建一个可以接受的新验证器,但如果我想出一种允许用户选择的方法,它会很简洁。
是否有某种方法可以操作按位运算符?
Field(validators = required&(postal_code|zip_code))
或者我只是让事情变得过于复杂并让自己陷入困境?
答案 0 :(得分:4)
Django通过使用Q
个对象来解决这个问题,这些对象可以使用&
和|
组合来创建更复杂的条件。模仿他们使用的东西可能是一个可以接受的解决方案。
答案 1 :(得分:1)
如果列表的项目是单个验证程序,或者and
一起进行验证的列表,那么顶级列表会对所有项目执行or
。你可以通过另一种方式做到这一点,当然,但通常是“并且按照惯例更严格地绑定”,所以这似乎是可以接受的。
更明确地说,您可以使用文字(引用)字符串'and'
,'or'
(以及可能'nand'
和'nor'
!)作为“运算符”的项目 - - 如果字符串的第一项(顶级或子字符串)是这样的运算符,它会说明如何处理所有其他字符串(默认值为'and'
)。
答案 2 :(得分:1)
您希望在验证程序类上实现 __或__(self,other)和 __以及__(self,other),它会动态返回一个知道如何的验证程序做适当的工作。因此,您基本上希望实现验证器,以便它们可以以这种方式动态组合(即,如果它们使用正则表达式,并且您可以对正则表达式的编写方式进行假设,则可以组合正则表达式适当地在您返回的新验证器中。)
http://docs.python.org/reference/datamodel.html#emulating-numeric-types
答案 3 :(得分:1)
sqlobject使用类似这样的东西,这是一个例子:
MyTable.select((MyTable.q.name == "bob") | (MyTable.q.age == 5))
这种方法的主要问题是运营商的优先级。它需要更多的括号来做得很好。一种更好的方法是使用And()和Or()函数并使用前缀表示法而不是中缀表示法。这样做的好处是,正在阅读代码的新程序员可以发现它。
在上面的示例中,我建议使用以下内容:
Field(validators=[required, Or(postal_code, zip_code)])
此列表中的所有验证器都隐含在一起。这使得琐碎的案例变得容易(琐碎的案例意味着“匹配所有这些验证器”)然后可能有相当复杂的表达式,例如:
Field(validators=Or(And(IsAmerica(), zip_code),
And(Not(IsAmerica()), city))])
当然,这只是一个建议。如图所示,使用&和|在某些系统中工作正常(Django,sqlobject)。在我的例子中你可以清楚地看到,复杂的案例在多层括号中存在问题,这是你应该考虑的权衡。