Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,71 @@ http://www.postgresql.org/docs/9.4/interactive/functions-net.html
``__min_prefixlen``
Minimum value (inclusive) for ``CIDR`` prefix, does not distinguish between IPv4 and IPv6

Database Functions
''''''''''''''''''

`Postgres network address functions <https://www.postgresql.org/docs/11/functions-net.html>`_ are exposed via the ``netfields.functions`` module. They can be used to extract additional information from these fields or to construct complex queries.

.. code-block:: python

from django.db.models import F

from netfields import CidrAddressField, NetManager
from netfields.functions import Family, Masklen

class Example(models.Model):
inet = CidrAddressField()
# ...

ipv4_with_num_ips = (
Example.objects.annotate(
family=Family(F('inet')),
num_ips=2 ** (32 - Masklen(F('inet'))) # requires Django >2.0 to resolve
)
.filter(family=4)
)

**CidrAddressField and InetAddressField Functions**

+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| Postgres Function | Django Function | Return Type | Description |
+================================+==================+======================+================================================================+
| abbrev(``T``) | Abbrev | ``TextField`` | abbreviated display format as text |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| broadcast(``T``) | Broadcast | ``InetAddressField`` | broadcast address for network |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| family(``T``) | Family | ``IntegerField`` | extract family of address; 4 for IPv4, 6 for IPv6 |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| host(``T``) | Host | ``TextField`` | extract IP address as text |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| hostmask(``T``) | Hostmask | ``InetAddressField`` | construct host mask for network |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| masklen(``T``) | Masklen | ``IntegerField`` | extract netmask length |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| netmask(``T``) | Netmask | ``InetAddressField`` | construct netmask for network |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| network(``T``) | Network | ``CidrAddressField`` | extract network part of address |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| set_masklen(``T``, int) | SetMasklen | ``T`` | set netmask length for inet value |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| text(``T``) | AsText | ``TextField`` | extract IP address and netmask length as text |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| inet_same_family(``T``, ``T``) | IsSameFamily | ``BooleanField`` | are the addresses from the same family? |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| inet_merge(``T``, ``T``) | Merge | ``CidrAddressField`` | the smallest network which includes both of the given networks |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+

**MACAddressField Functions**

+--------------------------------+------------------+----------------------+----------------------------------------------------------------+
| Postgres Function | Django Function | Return Type | Description |
+================================+==================+======================+================================================================+
| trunc(``T``) | Trunc | ``T`` | set last 3 bytes to zero |
+--------------------------------+------------------+----------------------+----------------------------------------------------------------+

Indexes
'''''''

As of Django 2.2, indexes can be created for ``InetAddressField`` and ``CidrAddressField`` extra lookups directly on the model.

.. code-block:: python
Expand Down
111 changes: 111 additions & 0 deletions netfields/functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""Postgres network address functions.

https://www.postgresql.org/docs/11/functions-net.html
"""

from django.db.models import BooleanField, Func, IntegerField, TextField

from .fields import CidrAddressField, InetAddressField


class Abbrev(Func):
"""Function to abbreviate field as text."""

arity = 1
function = 'ABBREV'
output_field = TextField()


class Broadcast(Func):
"""Function to extract broadcast address for network."""

arity = 1
function = 'BROADCAST'
output_field = InetAddressField()


class Family(Func):
"""Function to extract family of address; 4 for IPv4, 6 for IPv6."""

arity = 1
function = 'FAMILY'
output_field = IntegerField()


class Host(Func):
"""Function to extract IP address as text."""

arity = 1
function = 'HOST'
output_field = TextField()


class Hostmask(Func):
"""Function to construct host mask for network."""

arity = 1
function = 'HOSTMASK'
output_field = InetAddressField()


class Masklen(Func):
"""Function to extract netmask length."""

arity = 1
function = 'MASKLEN'
output_field = IntegerField()


class Netmask(Func):
"""Function to construct netmask for network."""

arity = 1
function = 'NETMASK'
output_field = InetAddressField()


class Network(Func):
"""Function to extract network part of address."""

arity = 1
function = 'NETWORK'
output_field = CidrAddressField()


class SetMasklen(Func):
"""Function to set netmask length."""

arity = 2
function = 'SET_MASKLEN'


class AsText(Func):
"""Function to extract IP address and netmask length as text."""

arity = 1
function = 'TEXT'
output_field = TextField()


class IsSameFamily(Func):
"""Function to test that addresses are from the same family."""

arity = 2
function = 'INET_SAME_FAMILY'
output_field = BooleanField()


class Merge(Func):
"""Function to calculate the smallest network which includes both of the given
networks.
"""

arity = 2
function = 'INET_MERGE'
output_field = CidrAddressField()


class Trunc(Func):

arity = 1
function = 'TRUNC'
3 changes: 2 additions & 1 deletion test/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ class Meta:


class AggregateTestModel(Model):
pass
network = CidrAddressField(blank=True, null=True, default=None)
inet = InetAddressField(blank=True, null=True, default=None)


class AggregateTestChildModel(Model):
Expand Down
Loading