Opened 6 years ago
Last modified 7 weeks ago
#31450 assigned Bug
Querying on ArrayField(PointField) returns string instead of list
| Reported by: | Nitin Sangwan | Owned by: | |
|---|---|---|---|
| Component: | contrib.postgres | Version: | 3.0 |
| Severity: | Normal | Keywords: | ArrayField, PointField |
| Cc: | Simon Charette | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | no |
Description
The following code
from django.db import models
from django.contrib.postgres.fields import ArrayField
from django.contrib.gis.db.models import PointField
class Foo(models.Model):
bar = ArrayField(models.TextField)
baz = ArrayField(PointField())
has this wrong behaviour:
x = Foo.objects.get(id=1)
x.bar # => ['Foo', 'Bar']
x.baz # => '{HexRepresentationofPoint1,HexRepresentationofPoint2}'
Attachments (1)
Change History (9)
by , 6 years ago
| Attachment: | postgis_tests.zip added |
|---|
comment:1 by , 6 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
Thanks for the report. Reproduced at 578c03b276e435bcd3ce9eb17b81e85135c2d3f3 with the attached test case.
comment:2 by , 6 years ago
| Has patch: | set |
|---|---|
| Owner: | set to |
| Patch needs improvement: | set |
| Status: | new → assigned |
comment:3 by , 6 years ago
Comment from the PR:
Thanks @Simon for your suggestion.
I've tried to create and register a new array type for geometry based on your suggestion at #8453. here is the code:
def get_geometry_oids(connection_alias):
with connections[connection_alias].cursor() as cursor:
cursor.execute("SELECT typarray FROM pg_type WHERE typname = 'geometry'")
return tuple(row[0] for row in cursor)
...
geometry_oids = get_geometry_oids(connection.alias)
new_type = psycopg2.extensions.new_type(geometry_oids, "geometry", caster) # caster is function to cast hex to geometry object
array_type = psycopg2.extensions.new_array_type(geometry_oids, 'geometry[]', new_type)
psycopg2.extensions.register_type(array_type, None)
The problem is that in caster function, I get all items in array not one item. something like this:
0101000020E610000000000000000018400000000000003840:0101000020E610000000000000000014400000000000003740
which is represent two points that seprated by :.
I've checed the column value in postgres console. for an array of points I got this:
{0101000020E6100000000000000000F03F0000000000000040:0101000020E6100000000000000000F03F0000000000000040}
While, I got below value for an array of chars:
{foo,bar}
the difference between two cases is for an array of points I got : as a separator, but for an array of chars I got ,.
I also tried to insert data from console to an array of points column by:
insert into test values (ARRAY[st_geomFromText('POINT(1 1)', 4326), st_geomFromText('POINT(1 1)', 4326)]);
the result was the same(: as separator).
Do you have any idea?
comment:4 by , 6 years ago
| Cc: | added |
|---|
comment:5 by , 6 years ago
I spent a few hours trying to figure it out but it looks like there might be something wrong with psycopg2. When registering an array type for geometry from the retrieved oid it simply doesn't get invoked for columns of type geometry(POINT, srid)[] behind ArrayField(PointField()).
Hasan your code is registering an array type and a scalar type for the same oid, you want to register a type for the scalar oid and an array type for array oid. Look at how get_hstore_oids and psycopg2.extras.register_hstore do it.
comment:6 by , 5 years ago
| Owner: | removed |
|---|---|
| Status: | assigned → new |
comment:7 by , 8 months ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:8 by , 7 weeks ago
| Owner: | removed |
|---|
Reproduce test case for #31450