app/django/contrib/gis/db/models/sql/where.py
author Lennard de Rijk <ljvderijk@gmail.com>
Fri, 24 Jul 2009 21:00:04 +0200
changeset 2678 a525a55833f1
parent 323 ff1a9aa48cfd
permissions -rw-r--r--
Send out a Notification upon creation of a new Request entity. The receivers are specified by the corresponding Role logic this Role Request is for. Currently Organization and Club Administrators will receive "new request" messages about respectively Mentor and Club Membership requests. Fixes Issue 442.

import datetime
from django.db.models.fields import Field
from django.db.models.sql.where import WhereNode
from django.contrib.gis.db.backend import get_geo_where_clause, SpatialBackend

class GeoAnnotation(object):
    """
    The annotation used for GeometryFields; basically a placeholder
    for metadata needed by the `get_geo_where_clause` of the spatial
    backend.
    """
    def __init__(self, field, value, where):
        self.geodetic = field.geodetic
        self.geom_type = field._geom
        self.value = value
        self.where = tuple(where)

class GeoWhereNode(WhereNode):
    """
    Used to represent the SQL where-clause for spatial databases --
    these are tied to the GeoQuery class that created it.
    """
    def add(self, data, connector):
        """
        This is overridden from the regular WhereNode to handle the 
        peculiarties of GeometryFields, because they need a special 
        annotation object that contains the spatial metadata from the 
        field to generate the spatial SQL.
        """
        if not isinstance(data, (list, tuple)):
            return super(WhereNode, self).add(data, connector)
        alias, col, field, lookup_type, value = data     
        if not hasattr(field, "_geom"):
            # Not a geographic field, so call `WhereNode.add`.
            return super(GeoWhereNode, self).add(data, connector)
        else:
            # `GeometryField.get_db_prep_lookup` returns a where clause
            # substitution array in addition to the parameters.
            where, params = field.get_db_prep_lookup(lookup_type, value)

            # The annotation will be a `GeoAnnotation` object that
            # will contain the necessary geometry field metadata for
            # the `get_geo_where_clause` to construct the appropriate
            # spatial SQL when `make_atom` is called.
            annotation = GeoAnnotation(field, value, where)
            return super(WhereNode, self).add((alias, col, field.db_type(), lookup_type,
                                               annotation, params), connector)

    def make_atom(self, child, qn):
        table_alias, name, db_type, lookup_type, value_annot, params = child
 
        if isinstance(value_annot, GeoAnnotation):
            if lookup_type in SpatialBackend.gis_terms:
                # Getting the geographic where clause; substitution parameters
                # will be populated in the GeoFieldSQL object returned by the
                # GeometryField.
                gwc = get_geo_where_clause(table_alias, name, lookup_type, value_annot)
                return gwc % value_annot.where, params
            else:
                raise TypeError('Invalid lookup type: %r' % lookup_type)
        else:
            # If not a GeometryField, call the `make_atom` from the 
            # base class.
            return super(GeoWhereNode, self).make_atom(child, qn)