Browse Source

Fixes #460: Corrected ordering of IP addresses with differing prefix lengths

Jeremy Stretch 8 years ago
parent
commit
4f774f8ba6
1 changed files with 15 additions and 0 deletions
  1. 15 0
      netbox/ipam/models.py

+ 15 - 0
netbox/ipam/models.py

@@ -5,6 +5,7 @@ from django.core.exceptions import ValidationError
 from django.core.urlresolvers import reverse
 from django.core.urlresolvers import reverse
 from django.core.validators import MaxValueValidator, MinValueValidator
 from django.core.validators import MaxValueValidator, MinValueValidator
 from django.db import models
 from django.db import models
+from django.db.models.expressions import RawSQL
 
 
 from dcim.models import Interface
 from dcim.models import Interface
 from tenancy.models import Tenant
 from tenancy.models import Tenant
@@ -295,6 +296,18 @@ class Prefix(CreatedUpdatedModel):
         return STATUS_CHOICE_CLASSES[self.status]
         return STATUS_CHOICE_CLASSES[self.status]
 
 
 
 
+class IPAddressManager(models.Manager):
+
+    def get_queryset(self):
+        """
+        By default, PostgreSQL will order INETs with shorter (larger) prefix lengths ahead of those with longer
+        (smaller) masks. This makes no sense when ordering IPs, which should be ordered solely by family and host
+        address. Here, we alter the default ordering to use HOST(address) instead of the raw address value.
+        """
+        qs = super(IPAddressManager, self).get_queryset()
+        return qs.annotate(host=RawSQL('HOST(ipam_ipaddress.address)', [])).order_by('family', 'host')
+
+
 class IPAddress(CreatedUpdatedModel):
 class IPAddress(CreatedUpdatedModel):
     """
     """
     An IPAddress represents an individual IPv4 or IPv6 address and its mask. The mask length should match what is
     An IPAddress represents an individual IPv4 or IPv6 address and its mask. The mask length should match what is
@@ -317,6 +330,8 @@ class IPAddress(CreatedUpdatedModel):
                                       null=True, verbose_name='NAT IP (inside)')
                                       null=True, verbose_name='NAT IP (inside)')
     description = models.CharField(max_length=100, blank=True)
     description = models.CharField(max_length=100, blank=True)
 
 
+    objects = IPAddressManager()
+
     class Meta:
     class Meta:
         ordering = ['family', 'address']
         ordering = ['family', 'address']
         verbose_name = 'IP address'
         verbose_name = 'IP address'