#27014 closed Bug (fixed)
Raster support for spatial lookup breaks filtering by annotations
Reported by: | Tristen Georgiou | Owned by: | nobody |
---|---|---|---|
Component: | GIS | Version: | 1.10 |
Severity: | Release blocker | Keywords: | raster, spatial |
Cc: | Daniel Wiesmann | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
This maybe a very specific edge case; I noticed that my website unit tests break when I upgraded to 1.10 and it appears to occur when I filter spatially and then annotate and then filter upon that annotation. (using Python 3, and the django.contrib.gis.db.backends.postgis backend)
Here's code to reproduce:
models.py
from django.contrib.gis.db import models class Event(models.Model): enabled = models.BooleanField(default=True, db_index=True) location = models.PointField(geography=True) distance = models.IntegerField(default=5) objects = models.GeoManager()
And a unit test to show the error:
tests.py
from django.contrib.gis.measure import D from django.db.models import F from django.test import TestCase from django.contrib.gis.geos import Point from django.contrib.gis.db.models.functions import Distance from polls.models import Event class SampleTest(TestCase): def test_something(self): centre = Point(0.0, 0.0) query = Event.objects.filter(location__dwithin=(centre, D(km=5))) query = query.annotate( actual_distance=Distance('location', centre) ).filter( actual_distance__lte=F('distance') * 1000) print(list(query.all()))
And stacktrace:
Traceback (most recent call last): File "/Users/tristeng/PycharmProjects/rastertest/polls/tests.py", line 18, in test_something print(list(query.all())) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/query.py", line 256, in __iter__ self._fetch_all() File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/query.py", line 1085, in _fetch_all self._result_cache = list(self.iterator()) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/query.py", line 54, in __iter__ results = compiler.execute_sql() File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/sql/compiler.py", line 824, in execute_sql sql, params = self.as_sql() File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/sql/compiler.py", line 376, in as_sql where, w_params = self.compile(self.where) if self.where is not None else ("", []) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/sql/compiler.py", line 353, in compile sql, params = node.as_sql(self, self.connection) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/sql/where.py", line 79, in as_sql sql, params = compiler.compile(child) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/sql/compiler.py", line 353, in compile sql, params = node.as_sql(self, self.connection) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/lookups.py", line 155, in as_sql lhs_sql, params = self.process_lhs(compiler, connection) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/lookups.py", line 146, in process_lhs compiler, connection, lhs) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/lookups.py", line 67, in process_lhs return compiler.compile(lhs) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/sql/compiler.py", line 351, in compile sql, params = vendor_impl(self, self.connection) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/contrib/gis/db/models/functions.py", line 252, in as_postgresql return super(Distance, self).as_sql(compiler, connection) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/contrib/gis/db/models/functions.py", line 43, in as_sql return super(GeoFunc, self).as_sql(compiler, connection) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/expressions.py", line 521, in as_sql arg_sql, arg_params = compiler.compile(arg) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/db/models/sql/compiler.py", line 351, in compile sql, params = vendor_impl(self, self.connection) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/contrib/gis/db/models/functions.py", line 82, in as_postgresql self.value = connection.ops.Adapter(self.value, geography=self.geography) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/contrib/gis/db/backends/postgis/adapter.py", line 26, in __init__ self.ewkb = to_pgraster(obj) File "/Users/tristeng/venvs/djangotest/lib/python3.4/site-packages/django/contrib/gis/db/backends/postgis/pgraster.py", line 123, in to_pgraster 1, 0, len(rast.bands), rast.scale.x, rast.scale.y, AttributeError: 'PostGISAdapter' object has no attribute 'bands'
It looks like PostGISAdapter initializer needs to handle the additional case where the type of 'obj' passed into the constructor is actually of it's own type, otherwise it assumes its a PGRaster and attempts to convert it; do we need to check isinstance(obj, PostGISAdapter) and handle accordingly?
class PostGISAdapter(object): def __init__(self, obj, geography=False): """ Initialize on the spatial object. """ self.is_geometry = isinstance(obj, Geometry) # Getting the WKB (in string form, to allow easy pickling of # the adaptor) and the SRID from the geometry or raster. if self.is_geometry: self.ewkb = bytes(obj.ewkb) self._adapter = Binary(self.ewkb) else: self.ewkb = to_pgraster(obj) self.srid = obj.srid self.geography = geography
Change History (7)
comment:1 by , 8 years ago
Severity: | Normal → Release blocker |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 8 years ago
Cc: | added |
---|
comment:3 by , 8 years ago
I just ran into this problem and have created a minimal test case to reproduce it here:
https://github.com/mcallistersean/django/commit/6a2e6c69feb27b2d097020959151a12dfe65963b
comment:4 by , 8 years ago
I am on holidays until the end of this week, but I'll have a look at the problem as soon as I am back early next week.
Daniel, could you take a look? I believe bbfad84dd980a97174c3b061a3d1b5f1373c380d is the relevant commit.