Opened 87 minutes ago
Last modified 71 minutes ago
#37322 new Bug
Saving to SpatialField(srid=None) persists NULL instead of raising an error
| Reported by: | Jacob Walls | Owned by: | |
|---|---|---|---|
| Component: | GIS | Version: | 6.1 |
| Severity: | Release blocker | Keywords: | srid |
| Cc: | Simon Charette | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
At least one user has tried to use spatial fields with a definition of srid=None, see forum. I'm pretty certain that's invalid usage.
Django can't create a migration to create such a spatial column with srid=None[0], but you can imagine a user trying this with an unmanaged model.
In Django 6.0, trying to save values to such a field raised DatabaseError, because None compiled to the string "None" and crashed.
After 1a8fd5cf75bf855852f6bc2f75c3da9f7b145669 (#36727, Django 6.1) implemented proper parameterization for srid values in spatial queries, None compiled to NULL, which zeroed out the value (because ST_Transform(..., NULL) returns NULL).
Suggesting we throw an error for this case in Python before letting the query persist NULL.
Test case on DryORM:
(You could probably construct a version of this test case using only output_field=GeometryField(srid=None)).)
from django.contrib.gis.db import models from django.contrib.gis.geos import GEOSGeometry from django.db.models.expressions import Value class Person(models.Model): # Create this field without srid=None for the sake of creating # a working migration. home = models.PointField(null=True) def run(): # Because Django migrated this model, restore the model field # to have srid=None, to simulate an unmanaged model. home = Person._meta.get_fields()[1] home.srid = None me = Person.objects.create() me.home = GEOSGeometry("POINT(1 1)", srid=4326) me.save() me.refresh_from_db() assert me.home # raises
Rerunning that snippet on 6.0 gives a DatabaseError instead. We can raise an error in the ORM layer instead.
[0] At least on PostGIS, because of a %d placeholder. I can check other backends shortly.
Change History (2)
comment:1 by , 71 minutes ago
comment:2 by , 71 minutes ago
| Summary: | Saving to SpatialField(srid=None) persists NULL instead of raising DatabaseError → Saving to SpatialField(srid=None) persists NULL instead of raising an error |
|---|
MySQL/MariaDB: a Django migration to create this column works, but transforms aren't supported, so never attempted
Spatialite: can't create the column: "django.db.utils.OperationalError: no such column: None"
Oracle: can't create the column: "django.db.utils.DatabaseError: ORA-00984: column not allowed here