Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#32122 closed Uncategorized (wontfix)

Querying GenericIPAddressField for inexact matches requires use of QuerySet.extra

Reported by: Peter Law Owned by: nobody
Component: Database layer (models, ORM) Version: 2.2
Severity: Normal Keywords: QuerySet.extra
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Given some model with a GenericIPAddressField field, I'd like to be able to query for IP addresses which are contained within ranges expressed by existing rows in the database (and also be able to do the inverse - query for rows matching a range).
I'm not sure if this is something which databases other than Postgres support natively though.

class There(models.Model):
    ip_address = models.GenericIPAddressField()

There.objects.create(ip_address='127.0.0.1/16')
There.objects.create(ip_address='1.1.1.1')

# I want this (or something like it) to return the first entry:
There.objects.get(ip_address__contains='127.0.0.2')
# Just like this does
There.objects.extra(where=("ip_address >> '127.0.0.2'",)).get()

# Similarly, I want this (or something like it) to return the second entry:
There.objects.get(ip_address__contained_by='1.1.0.0/16')
# Just like this does
There.objects.extra(where=("ip_address << '1.1.0.0/16'",)).get()

Currently the first example here ends up using the naive interpretation of contains -- surrounding the IP address with % and searching for that. For this reason there may be a need to pick a different keyword.

https://www.postgresql.org/docs/11/functions-net.html contains all the operators which Postgres supports, it would be great if Django supported them too.

Alternatively, if there's another way to achieve this which doesn't rely on QuerySet.extra and which I've missed then I'd be happy to use that.

Change History (1)

comment:1 by Simon Charette, 4 years ago

Resolution: wontfix
Status: newclosed

I suggest you have a look at the custom lookups documentation.

Something along these lines should work

from django.db.models import Lookup

class GenericIPAddressFieldContainedBy(Lookup):
    name = 'contained_by'

    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 << %s' % (lhs, rhs), params

models.GenericIPAddressField.register_lookup(GenericIPAddressFieldContainedBy)

Please TicketClosingReasons/UseSupportChannels next time as this is likely something you could have received support for there.

Version 0, edited 4 years ago by Simon Charette (next)
Note: See TracTickets for help on using tickets.
Back to Top