有人知道如何将Django模型字段验证器OR组合在一起吗?
类似这样的东西:
example_field = models.CharField(max_length=255, validators=[validator1|validator2])
我猜有一种方法,它涉及Q算子,但我找不到它到底是什么。
您可以在函数本身中进行验证:
from django.core.exceptions import ValidationError
from django.db import models
def combined_validator(value):
try:
return validator1(value)
except ValidationError:
return validator2(value)
class MyModel(models.Model):
example_field = models.CharField(
max_length=255,
validators=[combined_validator]
)
如果validator1
没有检测到任何故障,则返回控制流,因此我们是安全的。如果它引发一个ValidationError
,那么我们回退到validator2
。如果这没有引起错误,那么我们又安全了。否则,错误将从combined_validator
中引发。
我也需要一个OR验证器,所以我做了一个可重复使用的小验证器可以接受任意数量的"或"运算在一起的子验证器。受Django自己的验证器的启发,因此应该在任何地方都能工作(仅在Django Rest Framework序列化程序中测试(
from django.core.exceptions import ValidationError
from django.core.validators import EmailValidator, RegexValidator
from django.utils.deconstruct import deconstructible
from rest_framework import serializers
@deconstructible # allows usage in migrations
class OrValidator:
message = 'Enter a valid value.' # customize this based on the sub-validators
code = 'invalid'
def __init__(self, validators, message=None, code=None):
self.validators = validators
self._errors = []
if code is not None:
self.code = code
if message is not None:
self.message = message
def __call__(self, value):
for validator in self.validators:
try:
return validator(value)
except ValidationError as e:
# save error for debugging
self._errors.append(e)
# non matched, raise error
raise ValidationError(self.message, code=self.code)
def __eq__(self, other):
return (
self.validators == other.validators and
isinstance(other, self.__class__) and
self.message == other.message and
self.code == other.code
)
class UsernameValidator(RegexValidator):
regex = re.compile(r'^[-w]+Z', re.UNICODE)
# example usage in Django Rest Framework (should work in forms and models as well)
class ResetPasswordSerializer(serializers.Serializer):
email_or_username = serializers.CharField(
required=True,
validators=[
OrValidator(
[EmailValidator(), UsernameValidator()],
message='Enter a valid email or username',
),
],
)