使用Django的PostgreSQL IP inet比较

时间:2019-04-01 17:56:19

标签: django postgresql django-models

在我的PostgreSQL数据库中,我有一个网络设备表。

我正在构建一个必须与此表进行交互的Django应用。我正在使用带有.get()和.filter()方法的模型,但是我不确定如何处理以下查询:

select * from my_table where ip << inet '10.93.1/24'

这应该获得像10.93.1.*这样的记录,而不是10.93.13.*,所以我不能只使用:

items = MyTable.objects.filter(ip__startswith='10.93.1')

此查询的django等效项是什么?

2 个答案:

答案 0 :(得分:1)

我找到了一个简单的解决方案:我使用的是另一种filter方法-extra,而不是QuerySet

所以,这是我的代码:

objList = MyTable.objects.extra(where=["ip << inet '{}'".format(ip)])

注意:where方法的extra自变量需要一个列表。然后,它将列表中的每个元素都视为一个条件,并将它们与AND组合在一起。因此,只传递一个字符串:

objList = MyTable.objects.extra(where="ip << inet '{}'".format(ip))

将导致extra将此字符串视为字符列表,这将导致查询:

...WHERE (i) AND (p) AND ( ) AND (<) AND (<) AND ( ) AND (i) AND (n) AND (e) AND (t) AND ( ) AND (') AND (1) AND (0) AND (.) AND (9) AND (3) AND (.) AND (1) AND (/) AND (2) AND (4) AND (')

答案 1 :(得分:0)

(自v2.2起)没有默认的查询,但是create one很容易:

from django.db.models import GenericIPAddressField
from django.db.models import Lookup

@GenericIPAddressField.register_lookup
class ContainedIn(Lookup):
    lookup_name = 'iscontainedin'

    def as_postgresql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return '%s << inet %s' % (lhs, rhs), params

然后您可以将查询与__iscontainedin一起使用:

MyTable.objects.filter(ip__iscontainedin='10.93.1/24')

对于创建查找所涉及的样板太不好了。如果您只使用一次,那么extra查询的麻烦确实更少。对于重复使用,适当命名的查找将更具可读性,并且维护的代码更少。