Reputation: 1435
In my PostgreSQL database, I have a table of network devices.
I am building a django app that has to interact with this table. I am using models with .get() and .filter() methods, but I am not sure how to deal with the following query:
select * from my_table where ip << inet '10.93.1/24'
This should get records like 10.93.1.*
, but not 10.93.13.*
, so I can't just use:
items = MyTable.objects.filter(ip__startswith='10.93.1')
What is the django equivalent for this query?
Upvotes: 1
Views: 1397
Reputation: 5730
There is no default lookup for that (as of v2.2), but it's easy to 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
Then you can use the lookup with __iscontainedin
:
MyTable.objects.filter(ip__iscontainedin='10.93.1/24')
Too bad about boilerplate involved in creating a lookup. If you're only using this once, an extra
query is indeed less trouble. For repeated use, an appropriately named lookup will be more readable and less code to maintain.
Upvotes: 0
Reputation: 1435
I found a simple solution: instead of filter
, I'm using another QuerySet
method - extra
.
So, here's my code now:
objList = MyTable.objects.extra(where=["ip << inet '{}'".format(ip)])
Note: where
argument of extra
method expects a list. It then treats each element of the list as a condition, and combines them with AND
. So, passing just a string:
objList = MyTable.objects.extra(where="ip << inet '{}'".format(ip))
would cause extra
to treat this string as a list of characters, which would result in a query:
...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 (')
Upvotes: 1