diff --git a/netbox/ipam/migrations/0008_prefix_change_order.py b/netbox/ipam/migrations/0008_prefix_change_order.py new file mode 100644 index 000000000..3ad3eb9e3 --- /dev/null +++ b/netbox/ipam/migrations/0008_prefix_change_order.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-09-15 16:08 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0007_prefix_ipaddress_add_tenant'), + ] + + operations = [ + migrations.AlterModelOptions( + name='prefix', + options={'ordering': ['vrf', 'family', 'prefix'], 'verbose_name_plural': 'prefixes'}, + ), + ] diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 0b8b09049..c602fa3e0 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -12,6 +12,7 @@ from dcim.models import Interface from extras.models import CustomFieldModel, CustomFieldValue from tenancy.models import Tenant from utilities.models import CreatedUpdatedModel +from utilities.sql import NullsFirstQuerySet from .fields import IPNetworkField, IPAddressField @@ -192,7 +193,7 @@ class Role(models.Model): return self.vlans.count() -class PrefixQuerySet(models.QuerySet): +class PrefixQuerySet(NullsFirstQuerySet): def annotate_depth(self, limit=None): """ @@ -249,7 +250,7 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): objects = PrefixQuerySet.as_manager() class Meta: - ordering = ['family', 'prefix'] + ordering = ['vrf', 'family', 'prefix'] verbose_name_plural = 'prefixes' def __unicode__(self): diff --git a/netbox/utilities/sql.py b/netbox/utilities/sql.py new file mode 100644 index 000000000..617586ab8 --- /dev/null +++ b/netbox/utilities/sql.py @@ -0,0 +1,32 @@ +from django.db import connections, models +from django.db.models.sql.compiler import SQLCompiler + + +class NullsFirstSQLCompiler(SQLCompiler): + + def get_order_by(self): + result = super(NullsFirstSQLCompiler, self).get_order_by() + if result: + return [(expr, (sql + ' NULLS FIRST', params, is_ref)) for (expr, (sql, params, is_ref)) in result] + return result + + +class NullsFirstQuery(models.sql.query.Query): + + def get_compiler(self, using=None, connection=None): + if using is None and connection is None: + raise ValueError("Need either using or connection") + if using: + connection = connections[using] + return NullsFirstSQLCompiler(self, connection, using) + + +class NullsFirstQuerySet(models.QuerySet): + """ + Override PostgreSQL's default behavior of ordering NULLs last. This is needed e.g. to order Prefixes in the global + table before those assigned to a VRF. + """ + + def __init__(self, model=None, query=None, using=None, hints=None): + super(NullsFirstQuerySet, self).__init__(model, query, using, hints) + self.query = query or NullsFirstQuery(self.model)