Django 1.1.1:如何在PostgreSQL中存储空IP地址?
我正在写一个Django应用程序,用来存储IP地址和可选的路由信息。我创建的IP模型中有一个字段叫做nexthop
(表示下一个跳转的路由),这个字段通常是空的。最开始我们打算使用MySQL,但现在项目的要求变成了使用PostgreSQL。
这是我模型的简化版本:
class IP(models.Model):
address = models.IPAddressField()
netmask = models.IPAddressField(default='255.255.255.255')
nexthop = models.IPAddressField(null=True, blank=True, default=None)
active = models.BooleanField('is active?', default=1)
在使用MySQL的时候,我没有问题让nexthop
字段保持空白。然而,现在我把开发环境切换到Postgres后,我们遇到了一个在Django 1.1.1中已知的问题,空白的IP地址会引发DataError
。
invalid input syntax for type inet: ""
LINE 1: ...-14 13:07:29', 1, E'1.2.3.4', E'255.255.255.255', E'', true)
^
正如你所看到的,它出错了,因为它试图插入一个空字符串,而这个字段只接受NULL
。
我非常需要这个字段可以保持空白,因为如果一个IP没有下一个跳转,它的行为就会改变。
除了手动修改Django的代码,这是我最后的选择,我还考虑过把下一个跳转的默认值设为255.255.255.255,并围绕这个值写一些业务逻辑(比如,如果下一个跳转是255.255.255.255,就当作正常路由处理),但这感觉像是个临时解决办法。
我想知道有没有更好的方法来解决这个问题,不需要修改Django或写一些不太优雅的逻辑,或者有没有完全不同的方案可以满足我的需求。
提前感谢你的帮助!
编辑:临时解决方案
目前(作为一个临时修复),我决定使用下一个跳转的哨兵值:
在模型中:
IP_NEXTHOP_SENTINEL = '255.255.255.255'
class IP(models.Model):
nexthop = models.IPAddressField(
null=True,
blank=True,
default=IP_NEXTHOP_SENTINEL,
help_text='Use %s to indicate no next-hop' % IP_NEXTHOP_SENTINEL
)
def save(self, *args, **kwargs):
## hack for Django #5622 (http://code.djangoproject.com/ticket/5622)
if self.nexthop and self.nexthop == IP_NEXTHOP_SENTINEL:
self.nexthop = None
概述:
在管理员门户之外创建IP
对象的功能正常,这就是我在nexthop
字段上保留null=True
参数的原因。唯一会把255.255.255.255设置为下一个跳转的地方就是通过管理员门户,所以我决定重载save()
方法,让它总是把哨兵值替换为None
,这样我就能得到我想要的最终结果,而且感觉并不算太像是个临时解决方案。
谢谢你的建议!
3 个回答
那用空字符串作为标记,代替 255.255.255.255 呢?
因为后台管理系统把空字段存储为空字符串(当 blank=true
时),这个方法对用户来说更透明,不会强迫用户使用一个假的值……
你有没有试过只给 nexthop
设置 blank=True
,而不是同时设置 blank=True
和 null=True
?正如在Django文档中提到的:
只有在非字符串类型的字段,比如整数、布尔值和日期,才使用
null=True
。
如果你能说服开发者接受其中一个修复补丁,我建议你就先用这个修复过的Django版本,等正式的修复版本出来。如果说服不了的话,像你提到的那样,使用一个特殊的值可能会更简单,虽然这算是一种变通方法。你也可以用普通的 CharField
来代替 IPAddressField
,但这样的话,你就得自己处理验证的逻辑了。