Opened 9 years ago

Last modified 6 days ago

#28341 assigned Bug

GeometryField doesn't create GEOSGeometry objects lazily anymore

Reported by: Sergey Fedoseev Owned by: Abhimanyu Singh Negi
Component: GIS Version: 1.8
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Sergey Fedoseev)

Bisected to e9103402c0fa873aea58a6a11dba510cd308cb84 on test project with this script:

import mock
import sys

with mock.patch('django.utils.six.moves.html_parser'):
    import django
    from django.test import TestCase
    from django.contrib.gis.geos import Point

from test_app.models import City


def side_effect(*args, **kwargs):
    sys.exit(1)


django.setup()


with mock.patch('django.contrib.gis.db.models.fields.Geometry.__init__', side_effect=side_effect):
    City.objects.first()

This laziness is declared in GeoDjango Tutorial.

Change History (10)

comment:1 by Sergey Fedoseev, 9 years ago

Owner: changed from nobody to Sergey Fedoseev
Status: newassigned

comment:2 by Sergey Fedoseev, 9 years ago

Description: modified (diff)

comment:3 by Tim Graham, 9 years ago

Triage Stage: UnreviewedAccepted

comment:4 by Srinivas Reddy Thatiparthy, 9 years ago

Owner: changed from Sergey Fedoseev to Srinivas Reddy Thatiparthy

comment:7 by Srinivas Reddy Thatiparthy, 9 years ago

Apologies for spam - Are you working on this ? @SergeyFedoseev

comment:8 by Sergey Fedoseev, 9 years ago

Feel free to work on it.

comment:9 by Abhimanyu Singh Negi, 2 weeks ago

Owner: set to Abhimanyu Singh Negi

Hi, I spent some time digging into this and I think I understand what’s going on.

Right now geometry objects are being created too early. The conversion happens in the database converter layer — BaseSpatialOperations.get_db_converters() adds a geometry converter, and that converter runs in SQLCompiler.apply_converters(). So GEOSGeometry gets created while rows are being fetched, before the values ever reach the model instance. Because of that, SpatialProxy never sees raw values and the lazy-loading path isn’t used.

I traced this through the ORM flow and confirmed that model instances already contain GEOSGeometry objects in instance.dict, which explains why accessing the field later doesn’t trigger any conversion.

One important detail is that values() and values_list() depend on converters returning geometry objects immediately, so converters can’t just be removed. The fix needs to keep eager conversion for those cases but allow raw values when loading model instances so SpatialProxy can do the conversion lazily.

I’m going to try implementing this by adjusting the geometry converter / registration logic so conversion is skipped when loading model instances, then add a regression test and run the GIS test suite to make sure nothing else breaks.

Assigning this issue to myself for implementation.

comment:10 by Abhimanyu Singh Negi, 2 weeks ago

Has patch: set

comment:11 by Abhimanyu Singh Negi, 2 weeks ago

I have opened a pr addressing this issue(https://github.com/django/django/pull/20687)

During my investigation I confirmed that GeometryField values were being converted to GEOSGeometry obejcts, and Spatial proxy never receives the values the loading is bypassed

What i tried to do was to try distinguish model instance coming from values( queries ) so that raw WKB can be returned for model feilds, but due to lack of enogh query context they couldnt be distinuished properly

so i tried a diffrent approach, the backend converters return raw db values and the lazy conversion is handeled as intended by Spatial Proxy. So the values(), values_list(), annotations, and aggreagates are explicitly converted at result part, where the query context and output feilds are there.

So this restores the lazy loading while keeping the existing behaviour of the values() and aggregation queries.

Note: setting up and running the GIS tests required installing GDAL/PostGIS locally, and some GIS related jobs are failing in the CI, any guidance on how to fix that would be appriciated

comment:12 by Jacob Walls, 6 days ago

Has patch: unset
Note: See TracTickets for help on using tickets.
Back to Top