Code

Opened 3 years ago

Closed 3 years ago

Last modified 3 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)

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.

Attachments (0)

Change History (11)

comment:1 Changed 3 years ago by BernhardEssl

  • Easy pickings unset
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 3 years ago by anonymous

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 follow-up: Changed 3 years ago by aaugustin

  • Triage Stage changed from Unreviewed to Design 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.

comment:4 in reply to: ↑ 3 ; follow-ups: Changed 3 years ago by 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()?

comment:5 in reply to: ↑ 4 Changed 3 years ago by anonymous

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.

comment:6 in reply to: ↑ 4 ; follow-up: Changed 3 years ago by 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.

Last edited 3 years ago by aaugustin (previous) (diff)

comment:7 in reply to: ↑ 6 Changed 3 years ago by anonymous

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 follow-up: Changed 3 years ago by aaugustin

Maybe. Feel free to submit a patch!

comment:9 in reply to: ↑ 8 Changed 3 years ago by anonymous

Replying to aaugustin:

Maybe. Feel free to submit a patch!

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

comment:10 Changed 3 years ago by jacob

  • Resolution set to wontfix
  • Status changed from new to closed

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 Changed 3 years ago by ramiro

  • Description modified (diff)

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.