title: Django 1.1.1: How should I store an empty IP address using PostgreSQL?
body: <p>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 <code>nexthop</code> (for next-hop routes), which will usually be empty.  Originally we intended to use MySQL, but now project requirements have changed to use PostgreSQL.</p>
  
  <p>Here is a stripped down version of my model:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>So, with MySQL I did not have a problem leaving the <code>nexthop</code> field empty. However, now that I switched the development environment to Postgres, we've run into a <a href="http://code.djangoproject.com/ticket/5622" rel="nofollow noreferrer">known issue in Django 1.1.1</a> in which a blank IP address raises a <code>DataError</code></p>
  
  <pre><code>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)
                                                               ^
  </code></pre>
  
  <p>As you can see, it bombs because it is trying to insert an empty string when the column will only accept a <code>NULL</code>.</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>Thanks in advance!</p>
  
  <p><strong>Edit: Interim Solution</strong></p>
  
  <p>For the time-being (as an interstitial fix) I decided to go with the sentinel value for the next-hop:</p>
  
  <p>In the model:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Overview:</p>
  
  <p>Creation of <code>IP</code> objects outside of the admin portal works as intended, which is why I kept the <code>null=True</code> argument on the <code>nexthop</code> 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 <code>save()</code> to always replace the sentinel with <code>None</code> would give me the final result I desire and it doesn't really feel too much like a hack. </p>
  
  <p>Thanks for your input on this!</p>