Opened 9 years ago

Last modified 9 years ago

#25446 new New feature

Can't use PostGIS function ST_OrderingEquals with GeoDjango — at Version 1

Reported by: Evan Heidtmann Owned by: nobody
Component: GIS Version: dev
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 Evan Heidtmann)

Unless I'm missing something, Django 1.8 provides no facility in the ORM to use the ST_OrderingEquals() function to compare two geometries. I would like to use this function in a query.

Am I correct? If so, I may attempt a patch or at least a workaround.

Thanks!

Ref: http://postgis.net/docs/manual-1.3/ch06.html#ST_OrderingEquals

P.S. It's another question entirely whether the 'exact' lookup should use this function. For comparison, two LineString objects with opposite vertex ordering are not considered equal, so why should they be considered equal at the DB level?

Change History (1)

comment:1 by Evan Heidtmann, 9 years ago

Description: modified (diff)

For other users who may find this, here's my workaround that allows me to find the geometry that matches an input geometry, both in vertex values and in vertex ordering. A Django wizard may be able to improve this and I would welcome any criticism.

class SegmentModel(models.Model):
    ...

    @classmethod
    def get_or_create_for_line(cls, line):
        from django.contrib.gis.db.backends.postgis.adapter import PostGISAdapter

        # We have to run a query outside of Manager.raw() because Manager.raw()
        # always supplies a params argument to cursor.execute(), and sometimes
        # the binary form of the line contains a percent sign.
        from django.db import connection
        with connection.cursor() as cursor:
            sql = 'SELECT id FROM ride_segment WHERE line ~= {line_serialized} AND ST_OrderingEquals(line, {line_serialized})'.format(
                line_serialized=str(PostGISAdapter(line)))
            cursor.execute(sql)
            ids = cursor.fetchmany()

        if len(ids) > 1:
            raise cls.MultipleObjectsReturned('Multiple segments for line {}'.format(line.ewkt))
        elif len(ids) == 0:
            return (cls.objects.create(line=line), True)
        else:
            return (cls.objects.get(id=ids[0][0]), False)


Last edited 9 years ago by Evan Heidtmann (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top