我正在编写一个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,我们遇到了known issue in 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或编写hacky逻辑,或者完全不同的方法可以满足我的要求。
提前致谢!
编辑:临时解决方案
暂时(作为插页式广告修补)我决定使用下一跳的哨兵值:
在模型中:
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
个对象按预期工作,这就是我在null=True
字段上保留nexthop
参数的原因。将255.255.255.255设置为下一跳的唯一地方是通过管理门户,所以我决定重载save()
以始终用None
替换标记将给我最终结果我渴望并且它并不像黑客那样感觉太过分。
感谢您对此的意见!
答案 0 :(得分:2)
如果你可以说服开发者接受其中一个补丁,我会说只需运行修补后的Django副本,直到补丁版本登陆。如果没有,那么就像你建议的那样使用哨兵值可能不那么令人头疼,即使它是一个黑客。您也可以使用常规CharField
而不是IPAddressField
,但是您必须自己维护验证逻辑。
答案 1 :(得分:1)
您是否尝试仅使用blank=True
nexthop
而不是blank=True
和null=True
?如Django docs中所述:
仅对非字符串字段使用null = True,例如整数,布尔值和日期。
答案 2 :(得分:0)
那么使用空字符串作为哨兵,而不是255.255.255.255?
由于管理员后端将空字段存储为空字符串(当blank=true
时),此解决方案的优点是对用户透明,并且不会强迫他使用伪造的值...