在我的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等效项是什么?
答案 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
查询的麻烦确实更少。对于重复使用,适当命名的查找将更具可读性,并且维护的代码更少。