|
@@ -5,6 +5,7 @@ from django.core.exceptions import ValidationError
|
|
|
from django.core.urlresolvers import reverse
|
|
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
|
|
from django.db import models
|
|
|
+from django.db.models.expressions import RawSQL
|
|
|
|
|
|
from dcim.models import Interface
|
|
|
from extras.models import CustomFieldModel
|
|
@@ -296,6 +297,20 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel):
|
|
|
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. We can use HOST() to extract just the host portion of the address (ignoring its mask), but we must
|
|
|
+ then re-cast this value to INET() so that records will be ordered properly. We are essentially re-casting each
|
|
|
+ IP address as a /32 or /128.
|
|
|
+ """
|
|
|
+ qs = super(IPAddressManager, self).get_queryset()
|
|
|
+ return qs.annotate(host=RawSQL('INET(HOST(ipam_ipaddress.address))', [])).order_by('family', 'host')
|
|
|
+
|
|
|
+
|
|
|
class IPAddress(CreatedUpdatedModel, CustomFieldModel):
|
|
|
"""
|
|
|
An IPAddress represents an individual IPv4 or IPv6 address and its mask. The mask length should match what is
|
|
@@ -318,6 +333,8 @@ class IPAddress(CreatedUpdatedModel, CustomFieldModel):
|
|
|
null=True, verbose_name='NAT IP (inside)')
|
|
|
description = models.CharField(max_length=100, blank=True)
|
|
|
|
|
|
+ objects = IPAddressManager()
|
|
|
+
|
|
|
class Meta:
|
|
|
ordering = ['family', 'address']
|
|
|
verbose_name = 'IP address'
|