2012-05-31 36 views
1

我的Django模型是这样的:如何在Django中为模型字段编写验证器?

class Host(): 
    ipv4 = models.ChaField(max_length=39,verbose_name=_("IPv4"), validator= [ip_validator]) 
    ipv6 = models.CharField(max_length=39, verbose_name=_("IPv6"), 
         blank=True, null=True, validators= [ip_validator]) 

和我utils.py定义的ip_validator方法:

from netaddr import * 
def ip_validator(value): 
try: 
    ip_version = IPAddress(value).version() 
    if ip_version !=6: 
     raise ValidationError(u'%s Not a IPv6 address' % value) 
except ValueError: 
    raise ValidationError(u'%s Not a IPv6 address' % value) 

它工作正常,但我必须写IPv4的验证方法相同。这似乎是冗余而不是一个好主意。是否有可能为IPv4和IPv6编写通用方法。

我发现下面的示例做,但无法理解它是如何传递的参数来验证:

#!/usr/bin/env python 

class IPAddress(object): 
    def __init__(self, version): 
     self.version = version 

def validator_factory(ip_version): 
    def validate_ip_address(ip_address): 
     if ip_address.version != ip_version: 
      print "Invalid! :(" 
     else: 
      print "Valid! :D" 
    return validate_ip_address 

ipv4_validator = validator_factory(4) 
ipv6_validator = validator_factory(6) 

ipv4_address = IPAddress(4) 
ipv6_address = IPAddress(6) 

ipv4_validator(ipv4_address) 
ipv4_validator(ipv6_address) 
ipv6_validator(ipv6_address) 

如果这样做那么我们必须在validator = []

传递

已更新! 在models.py:

class Host(): 
    ipv4 = models.CharField(max_length=39,verbose_name=_("IPv4 address"), 
         validators=[validator_factory(4)]) 

这是调用验证程序的正确方法吗? 和utils.py:

from netaddr import * 

def validator_factory(ip_version): 
    def validate_ip_address(ipv4): 
     if IPAddress(ipv4).version != ip_version: 
      print "Invalid! :(" 
     else: 
      print "Valid! :D" 
    return validate_ip_address 

什么是这里的错吗?

+0

Django的1.4已经在内置['GenericIPPAddressField'](https://docs.djangoproject.com/en/dev/ref/models/fields/#genericipaddressfield)。使用'protocol'参数可以接受IPv4,IPv6或两种类型的地址。 – Alasdair

+0

@Alasdair但我使用Django 1.3 –

回答

2

因为ip_version变量关闭的validator_factory作品。工厂返回的内部函数可以访问ip_version变量。你会使用 ipv4_validatoripv6_validator功能验证程序列表中你的领域。

我会建议升级到1.4的Django如果可能的话,这样就可以使用或GenericIPAddressField。如果你需要坚持版本1.3,你可以从Django 1.4中移植代码。如果你坚持使用自己的验证器,我不会过于担心重复,只关注让两个验证器起作用。

+0

我无法理解解决方案。为了将数据传递给验证器,请在这里粘贴sudo代码。我正面临一个问题,我应该如何通过验证器中的模型字段的ip_version和ip_Address。因为我们只能从那里传递一个参数。 –

+0

查看代码中的更新部分。我尝试过这种情况,但没有任何反应(请参阅相关更新的章节) –

+0

您正在字段定义中正确使用validators参数。但是,您的验证器不会引发任何验证错误,因此它不会执行任何操作。恐怕我不能帮你调试验证器。现在已经有非常好的[包括在Django(https://docs.djangoproject.com/en/dev/ref/validators/#validate-ipv4-address),(IPv4的在Django 1.2+,IPV6在Django 1.4+ ),所以我建议你使用它们。 – Alasdair