Opened 13 years ago

Closed 13 years ago

Last modified 13 years ago

#16468 closed Bug (wontfix)

Django IPAddressField incorrectly casts values when querying

Reported by: anonymous Owned by: nobody
Component: Database layer (models, ORM) Version: 1.3
Severity: Normal Keywords:
Cc: Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Ramiro Morales)

Django 1.3 running Postgres 9.0

I have a simple model with an IPAddressField. Before today my app only placed simple IP addresses into it (192.168.1.1 for example), but I expanded the functionality to accept ip ranges with CIDR notations (192.168.1.1/28 for example).

When I use django to get all records with an IP address which has a CIDR notation it issues the following SQL statement (abbreviated):

SELECT ..blah.. FROM "x" WHERE (HOST("x"."target") = E'192.168.1.1/28' )

This is comparing a HOST to a string, and it returns 0 results even though there are several entries in the database. It returns the correct results when I alter the query and run it through my postgresql shell:

SELECT ..blah.. FROM "x" WHERE (HOST("x"."target") = HOST('192.168.1.1/28') )

In short (at least on Postgresql) any data being compared against a IPAddressField should be cast to a HOST instead of a string.

Change History (11)

comment:1 by Bernhard Essl, 13 years ago

Easy pickings: unset

comment:2 by anonymous, 13 years ago

Sample code:

class IPAddress(models.Model):
   target = models.IPAddressField()

for i in xrange(10):
   x = IPAddress(target="192.168.1.1")
   x.save()

print "We have %s IP's"%IPAddress.objects.filter(target="192.168.1.1").count()

for i in xrange(10):
   x = IPAddress(target="192.168.1.1/28")
   x.save()

print "We have %s IP's with CIDR notations"%IPAddress.objects.filter(target="192.168.1.1/28")

Outputs 10 and 0.

comment:3 by Aymeric Augustin, 13 years ago

Triage Stage: UnreviewedDesign decision needed

I'm not sure it's possible to implement the behavior you expect — with a reasonable amount of work, that is :(

Of course, you may use raw SQL as a workaround, but that's inconvenient.

The current docs don't say anything IP ranges; they only give examples with IP addresses. If we decide we can't support IP ranges, we should add a note.

in reply to:  3 ; comment:4 by anonymous, 13 years ago

Replying to aaugustin:

I'm not sure it's possible to implement the behavior you expect — with a reasonable amount of work, that is :(

Of course, you may use raw SQL as a workaround, but that's inconvenient.

The current docs don't say anything IP ranges; they only give examples with IP addresses. If we decide we can't support IP ranges, we should add a note.

Would it really be that hard to make a way to specify types when querying fields? Django knows not to cast integers to strings when querying an integer field, so if it is querying against a IPAddressField then just wrap the data in Host()?

in reply to:  4 comment:5 by anonymous, 13 years ago

Replying to anonymous:

Replying to aaugustin:

I'm not sure it's possible to implement the behavior you expect — with a reasonable amount of work, that is :(

Of course, you may use raw SQL as a workaround, but that's inconvenient.

The current docs don't say anything IP ranges; they only give examples with IP addresses. If we decide we can't support IP ranges, we should add a note.

Would it really be that hard to make a way to specify types when querying fields? Django knows not to cast integers to strings when querying an integer field, so if it is querying against a IPAddressField then just wrap the data in Host()?

Or on the flip side of this if Django does not use any of the inet() features in Postgresql or any other database and it compares strings with it then why not make IPAddress the same as a CharField with some additional regex validation? That would solve this issue and make more sense IMO.

in reply to:  4 ; comment:6 by Aymeric Augustin, 13 years ago

Replying to anonymous:

Would it really be that hard to make a way to specify types when querying fields? Django knows not to cast integers to strings when querying an integer field, so if it is querying against a IPAddressField then just wrap the data in Host()?

AFAIX, that depends on the type of the data you pass, not the type of the target field, and type("192.168.1.1/28") == str.

Version 0, edited 13 years ago by Aymeric Augustin (next)

in reply to:  6 comment:7 by anonymous, 13 years ago

Replying to aaugustin:

Replying to anonymous:

Would it really be that hard to make a way to specify types when querying fields? Django knows not to cast integers to strings when querying an integer field, so if it is querying against a IPAddressField then just wrap the data in Host()?

AFAIK, that depends on the type of the data you pass, not the type of the target field, and type("192.168.1.1/28") == str.

So wouldn't it be possible to make a pseudo type to handle hosts?

comment:8 by Aymeric Augustin, 13 years ago

Maybe. Feel free to submit a patch!

in reply to:  8 comment:9 by anonymous, 13 years ago

Replying to aaugustin:

Maybe. Feel free to submit a patch!

Sure, I will take a peek inside Django's internals.

comment:10 by Jacob, 13 years ago

Resolution: wontfix
Status: newclosed

I'm going to mark this wontfix: while we could make this work on Postgres, it wouldn't work on other databases (which store IP addresses as strings). That's a big problem for portability, and makes reusable apps a lot harder.

Thanks for the suggestion; sorry to have to reject. If only we could force the whole world to use Postgres...

comment:11 by Ramiro Morales, 13 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top