开发者

Django 1.1.1: How should I store an empty IP address using PostgreSQL?

开发者 https://www.devze.com 2022-12-13 15:50 出处:网络
I am writing a Django application that stores IP addresses with optional routing information.One of the fields for the IP model I have created is nexthop (for next-hop routes), which will usually be e

I am writing a Django application that stores IP addresses with optional routing information. One of the fields for the IP model I have created is nexthop (for next-hop routes), which will usually be empty. Originally we intended to use MySQL, but now project requirements have changed to use PostgreSQL.

Here is a stripped down version of my model:

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)

So, with MySQL I did not have a problem leaving the nexthop field empty. However, now that I switched the development environment to Postgres, we've run into a known issue in Django 1.1.1 in which a blank IP address raises a 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)
                                                             ^

As you can see, it bombs because it is trying to insert an empty string when the column will only accept a NULL.

I have a very real need to be able to keep this field empty, because if an IP doesn't have a next-hop, then its behavior changes.

Short of hacking the Django code manually, which is my ultimate last resort, I have also thought of defaulting next-hop to 255.255.255.255 and wrapping some business logic around that (i.e. If next-hop is 255.255.255.255, treat as normal route), but that just feels like a hack.

I would like to know if there are any suggestions on a better way to do this that would not require hacking Django or writing hacky logic, or if there is a completely different approach altogether that can satisfy my requirement.

Thanks in advance!

Edit: Interim Solution

For the time-being (as an interstitial fix) I decided to go with the sentinel value for the next-hop:

In the model:

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

Overview:

Creation of IP objects outside of the admin portal works as intended, which is why I kept the null=True argument on the nexthop field. The only place where 255.255.255.255 would ever be set as the next-hop would be through the admin portal, so I decided that overloading s开发者_高级运维ave() to always replace the sentinel with None would give me the final result I desire and it doesn't really feel too much like a hack.

Thanks for your input on this!


If you can convince the devs to accept one of the patches, I'd say just run a patched copy of Django until the patched version lands. If not, then it might be less headache to just use a sentinel value, as you suggested, even though it is a hack. You might also just use a regular CharField instead of an IPAddressField, but then you get stuck having to maintain validation logic on your own.


Have you tried just using blank=True for nexthop, rather than both blank=True and null=True? As noted in the Django docs:

Only use null=True for non-string fields such as integers, booleans and dates.


And what about using empty string as sentinel, instead of 255.255.255.255 ?

As admin back-end stores empty field as empty string (when blank=true), this solution has the advantage to be transparent for the user and doesn't force him to use a faked value...

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号