2012-05-31 72 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