Opened 2 years ago

Closed 20 months ago

Last modified 20 months ago

#33638 closed Bug (fixed)

Saving unique geography fields crashes in the admin on PostGIS.

Reported by: Sebastian Clarke Owned by: Jacob Walls
Component: GIS Version: 3.2
Severity: Normal Keywords:
Cc: Claude Paroz 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

If you define a model with a geometry point field that has geography=True and unique=True, the default admin interface generated for this model cannot save an existing instance.

When you save, you ultimately hit the error:

ValueError: PostGIS geography does not support the "~=" function/operator.

This is caused by the validate_unique() method on the model instance. When performing unique checks (in _perform_unique_checks()), it's forming a queryset with objects.filter(geometry=geometry) and (as noted in related issue https://code.djangoproject.com/ticket/27314) that results in the ~= operator being used in PostGIS which is not supported on geographic geometries.

We will work around this issue ourselves, by overriding validate_unique() on the model, passing the field in question to the exclude list in the super call, then doing our own manual check by instead using a filter like:

GeoModel.objects.filter(geometry__bboverlaps=point)

i.e., a bounding-box overlaps check.

For point fields, the concept of even having a bounding box, and how much sense that makes, I suppose is up for debate (points theoretically being of infinitely small size). However this check performs in the way we want and works as you might expect the equality operator to.

Have not confirmed whether the issue exists for geometry fields other than Point, or on versions other than 3.2 - but I strongly suspect so.

Simplest test case would be to have a models.py:

from django.contrib.gis.db import models

class Location(models.Model):
    geometry = models.PointField(geography=True, unique=True)

along with admin.py

from django.contrib.gis import admin
admin.site.register(Location, admin.OSMGeoAdmin)

and then try and save an existing instance when using the postgis db backend.

Change History (13)

comment:1 by Mariusz Felisiak, 2 years ago

Cc: Claude Paroz added
Summary: Model Admin for GIS models cannot save model with point field when (geography=True, unique=True) with postgis backendSaving unique geography fields crashes in the admin on PostGIS.
Triage Stage: UnreviewedAccepted

Tentatively accepted for future investigation. I was able to reproduce this issue, however using geography type is really limited on PostGIS (see docs) and __bboverlaps is not an option in the general case. I wonder how we could improve this, I can imagine two options:

  • raise a system warning when unique is used with geography and skip these fields in unique checks,
  • cast geography fields to a geometry type in the query.

What do you think?

Last edited 2 years ago by Mariusz Felisiak (previous) (diff)

comment:2 by Claude Paroz, 2 years ago

I think that casting is a track to explore.

comment:3 by Jacob Walls, 21 months ago

Owner: changed from nobody to Jacob Walls
Status: newassigned

comment:4 by Jacob Walls, 20 months ago

Has patch: set

comment:5 by Jacob Walls, 20 months ago

Patch needs improvement: set

A MySQL issue to look into.

comment:6 by Jacob Walls, 20 months ago

Patch needs improvement: unset

comment:7 by Mariusz Felisiak, 20 months ago

Patch needs improvement: set

comment:8 by Jacob Walls, 20 months ago

Patch needs improvement: unset

comment:9 by Mariusz Felisiak, 20 months ago

Patch needs improvement: set

comment:10 by Jacob Walls, 20 months ago

Patch needs improvement: unset

comment:11 by Mariusz Felisiak, 20 months ago

Triage Stage: AcceptedReady for checkin

comment:12 by Mariusz Felisiak <felisiak.mariusz@…>, 20 months ago

Resolution: fixed
Status: assignedclosed

In 4403432b:

Fixed #33638 -- Fixed GIS lookups crash with geography fields on PostGIS.

comment:13 by Mariusz Felisiak <felisiak.mariusz@…>, 20 months ago

In 714d59d5:

[4.2.x] Fixed #33638 -- Fixed GIS lookups crash with geography fields on PostGIS.

Backport of 4403432b759124aa613249373e0d2ede64ae8765 from main

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