Django PostgreSQL 网络字段实现
项目描述
本项目旨在为Django提供合适的PostgreSQL网络相关字段。在Django 1.4之前,内置的IPAddressField不支持IPv6,并且在所有查找中使用效率低下的HOST()强制类型转换。从1.4版开始,您可以使用GenericIPAddressField来处理IPv6,但强制类型转换的问题仍然存在。
除了基本的IPAddressField替换,InetAddressField,CidrAddressField,MACAddressField和MACAddress8Field之外,此库还提供了一个管理器,允许在ORM中直接进行基于IP的高级查找。
在Python中,IP地址字段的值表示为来自ipaddress模块的类型。在Python 2.x中,使用回滚。MAC地址字段表示为来自netaddr模块的EUI类型。
依赖项
本模块需要Django >= 1.11,psycopg2或psycopg,以及netaddr。
安装
$ pip install django-netfields
入门指南
确保netfields已包含在您的PYTHONPATH中,并在INSTALLED_APPS中。
InetAddressField将值存储在PostgreSQL中的类型为INET。在Python中,该值将表示为表示IP地址和网络掩码/前缀长度的对的一个ipaddress.ip_interface对象,除非设置了store_prefix_length参数为False,在这种情况下,该值将表示为一个ipaddress.ip_address对象。
from netfields import InetAddressField, NetManager
class Example(models.Model):
inet = InetAddressField()
# ...
objects = NetManager()
CidrAddressField将值存储在PostgreSQL中的类型为CIDR。在Python中,该值将表示为一个ipaddress.ip_network对象。
from netfields import CidrAddressField, NetManager
class Example(models.Model):
inet = CidrAddressField()
# ...
objects = NetManager()
MACAddressField将值存储在PostgreSQL中的类型为MACADDR。在Python中,该值将表示为一个netaddr.EUI对象。请注意,EUI对象的默认文本表示与netaddr模块不同。它以在网络工具和网络管理员中更常用的格式表示(00:11:22:aa:bb:cc)。
from netfields import MACAddressField, NetManager
class Example(models.Model):
inet = MACAddressField()
# ...
MACAddress8Field将值存储在PostgreSQL中的类型为MACADDR8。在Python中,该值将表示为一个netaddr.EUI对象。与MACAddressField一样,表示是常见的(00:11:22:aa:bb:cc:dd:ee)。
from netfields import MACAddress8Field, NetManager
class Example(models.Model):
inet = MACAddress8Field()
# ...
对于InetAddressField和CidrAddressField,需要NetManager以提供额外的查找功能。对于INET和CIDR数据库类型,查找处理方式与运行纯Django时不同。所有查找都是不区分大小写的,并且尽可能避免基于文本的查找。除了Django的默认查找类型外,还添加了以下内容
- __net_contained
包含在给定的网络中
- __net_contained_or_equal
包含在给定的网络中或等于给定的网络
- __net_contains
包含给定的地址
- __net_contains_or_equals
包含或等于给定的地址/网络
- __net_overlaps
包含或被给定的地址包含
- __family
与给定的地址族匹配
- __host
与地址的主部分匹配,无论前缀长度如何
- __prefixlen
与地址的前缀长度部分匹配
这些对应于https://postgresql.ac.cn/docs/9.4/interactive/functions-net.html中的运算符和函数
CidrAddressField包含两个额外的查找(这些将在未来由__prefixlen取代)
- __max_prefixlen
CIDR前缀的最大值(包含),不区分IPv4和IPv6
- __min_prefixlen
CIDR前缀的最小值(包含),不区分IPv4和IPv6
数据库函数
Postgres网络地址函数通过netfields.functions模块公开。它们可以用于从这些字段中提取额外的信息,或构建复杂的查询。
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和InetAddressField函数
Postgres函数 |
Django函数 |
返回类型 |
描述 |
---|---|---|---|
abbrev(T) |
缩写 |
文本字段 |
文本形式的缩写显示格式 |
广播(T) |
广播 |
网络地址字段 |
网络的广播地址 |
family(T) |
族 |
整数字段 |
提取地址的族;4为IPv4,6为IPv6 |
host(T) |
主机 |
文本字段 |
提取IP地址为文本 |
hostmask(T) |
主机掩码 |
网络地址字段 |
为网络构造主机掩码 |
masklen(T) |
掩码长度 |
整数字段 |
提取子网掩码长度 |
netmask(T) |
子网掩码 |
网络地址字段 |
为网络构造子网掩码 |
network(T) |
网络 |
CidrAddressField |
提取地址的网络部分 |
set_masklen(T, int) |
设置掩码长度 |
T |
为inet值设置子网掩码长度 |
text(T) |
AsText |
文本字段 |
提取IP地址和子网掩码长度为文本 |
inet_same_family(T, T) |
IsSameFamily |
布尔字段 |
地址是否来自同一族? |
inet_merge(T, T) |
Merge |
CidrAddressField |
包含给定两个网络的最小网络 |
MACAddressField 函数
Postgres函数 |
Django函数 |
返回类型 |
描述 |
---|---|---|---|
trunc(T) |
Trunc |
T |
将最后3个字节设置为0 |
MACAddress8Field 函数
Postgres函数 |
Django函数 |
返回类型 |
描述 |
---|---|---|---|
trunc(T) |
Trunc |
T |
将最后5个字节设置为0 |
macaddr8_set7bit(T) |
Macaddr8Set7bit |
T |
将第7位设置为1。用于生成链路本地IPv6地址 |
索引
截至Django 2.2,可以为< span class="docutils literal">InetAddressField和< span class="docutils literal">CidrAddressField创建索引,并直接在模型上执行额外查找。
from django.contrib.postgres.indexes import GistIndex
from netfields import CidrAddressField, NetManager
class Example(models.Model):
inet = CidrAddressField()
# ...
class Meta:
indexes = (
GistIndex(
fields=('inet',), opclasses=('inet_ops',),
name='app_example_inet_idx'
),
)
对于Django的早期版本,可以使用自定义迁移来安装索引。
from django.db import migrations
class Migration(migrations.Migration):
# ...
operations = [
# ...
migrations.RunSQL(
"CREATE INDEX app_example_inet_idx ON app_example USING GIST (inet inet_ops);"
),
# ...
]
类似项目
https://bitbucket.org/onelson/django-ipyfield 尝试解决与该库相同的一些问题。然而,与仅通过合适的字段类型支持postgres不同,ipyfield当前在其实现中使用 VARCHAR(39) 作为虚假的无符号64位数字。
历史
主存储库最初保存在 https://github.com/adamcik/django-postgresql-netfields 上。2013年4月下旬,该项目被移至 https://github.com/jimfunk/django-postgresql-netfields,以便将接力棒传递给真正使用此代码的人 :-)
项目详情
django-netfields-1.3.2.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e54943601bb88573b70f8843e7080f5d7327e41f5500ce30a198c384cc325a60 |
|
MD5 | 555466c3e4af6d19f9b14049897e58b2 |
|
BLAKE2b-256 | 1608034a97f1f9bff7a5e8ae3180d7a33cba4154a75e444d167366aee78ea61a |