Django

Code

Changeset 4884

Show
Ignore:
Timestamp:
03/31/07 16:25:29 (2 years ago)
Author:
jbronn
Message:

gis: two big changes:

(1) the addition of the GeoMixin? class, which gives geometry fields contributed functions (e.g. get_GEOM_area).
(2) geo_filter() is no more, all queries use filter() now.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/db/models/fields/__init__.py

    r4851 r4884  
    11# The Django base Field class. 
    22from django.db.models.fields import Field 
    3 from django.oldforms import LargeTextField 
    43from django.contrib.gis.db.models.postgis import POSTGIS_TERMS 
    5 from geos import geomToWKT, geomFromHEX 
     4from django.contrib.gis.oldforms import WKTField 
     5from django.utils.functional import curry 
    66 
    77#TODO: add db.quotename. 
     
    3636    return sql 
    3737 
    38 class WKTField(LargeTextField): 
    39     "An oldforms LargeTextField for editing WKT text in the admin." 
    40  
    41     def render(self, data): 
    42         # PostGIS uses EWKBHEX to store its values internally, converting 
    43         # to WKT for the admin first. 
    44         wkt = geomToWKT(geomFromHEX(data)) 
    45         return super(WKTField, self).render(wkt) 
    46  
    4738class GeometryField(Field): 
    4839    "The base GIS field -- maps to the OpenGIS Geometry type." 
     
    6556        super(GeometryField, self).__init__(**kwargs) 
    6657 
     58 
     59    def contribute_to_class(self, cls, name): 
     60        super(GeometryField, self).contribute_to_class(cls, name) 
     61 
     62        # Adding the WKT accessor function for geometry 
     63        setattr(cls, 'get_%s_wkt' % self.name, curry(cls._get_GEOM_wkt, field=self)) 
     64        setattr(cls, 'get_%s_centroid' % self.name, curry(cls._get_GEOM_centroid, field=self)) 
     65        setattr(cls, 'get_%s_area' % self.name, curry(cls._get_GEOM_area, field=self)) 
    6766 
    6867    def get_internal_type(self): 
     
    9998        "Using the WKTField (defined above) to be our manipulator." 
    10099        return [WKTField] 
    101      
     100 
    102101# The OpenGIS Geometry Type Fields 
    103102class PointField(GeometryField): 
  • django/branches/gis/django/contrib/gis/db/models/__init__.py

    r4851 r4884  
    22from django.db.models import * 
    33 
    4 # The GeoManager class. 
     4# The GeoManager 
    55from django.contrib.gis.db.models.manager import GeoManager 
    66 
     
    1111     GeometryCollectionField 
    1212 
     13# The geographic mixin class. 
     14from GeoMixin import GeoMixin 
  • django/branches/gis/django/contrib/gis/db/models/manager.py

    r4787 r4884  
    33 
    44class GeoManager(Manager): 
     5    "Overrides Manager to return Geographic QuerySets." 
    56 
    67    def get_query_set(self): 
    78        return GeoQuerySet(model=self.model) 
    8  
    9     def geo_filter(self, *args, **kwargs): 
    10         return self.get_query_set().geo_filter(*args, **kwargs) 
    11  
    12     def geo_exclude(self, *args, **kwargs): 
    13         return self.get_query_set().geo_exclude(*args, **kwargs) 
  • django/branches/gis/django/contrib/gis/db/models/postgis.py

    r4851 r4884  
    33from copy import copy 
    44from django.db import backend 
    5 from django.db.models.query import LOOKUP_SEPARATOR, find_field, FieldFound 
     5from django.db.models.query import LOOKUP_SEPARATOR, find_field, FieldFound, QUERY_TERMS, get_where_clause 
    66from django.utils.datastructures import SortedDict 
    77 
     
    4242    'equals' : 'Equals', 
    4343    'disjoint' : 'Disjoint', 
    44     'intersects' : 'Intersects', 
    4544    'touches' : 'Touches', 
    4645    'crosses' : 'Crosses', 
     
    5655POSTGIS_TERMS = list(POSTGIS_OPERATORS.keys()) # Getting the operators first 
    5756POSTGIS_TERMS.extend(list(POSTGIS_GEOMETRY_FUNCTIONS.keys())) # Adding on the Geometry Functions 
     57POSTGIS_TERMS = tuple(POSTGIS_TERMS) # Making immutable 
    5858 
    5959def get_geo_where_clause(lookup_type, table_prefix, field_name, value): 
     
    7373    except KeyError: 
    7474        pass 
    75  
     75     
    7676    # For any other lookup type 
    7777    if lookup_type == 'isnull': 
     
    8080    raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type) 
    8181 
    82 def geo_parse_lookup(kwarg_items, opts): 
     82def parse_lookup(kwarg_items, opts): 
    8383    # Helper function that handles converting API kwargs 
    8484    # (e.g. "name__exact": "tom") to SQL. 
    85     # Returns a tuple of (tables, joins, where, params). 
     85    # Returns a tuple of (joins, where, params). 
    8686 
    8787    # 'joins' is a sorted dictionary describing the tables that must be joined 
     
    113113        # term, assume that the query is an __exact 
    114114        lookup_type = path.pop() 
     115 
    115116        if lookup_type == 'pk': 
    116117            lookup_type = 'exact' 
    117118            path.append(None) 
    118         elif len(path) == 0 or lookup_type not in POSTGIS_TERMS
     119        elif len(path) == 0 or not ((lookup_type in QUERY_TERMS) or (lookup_type in POSTGIS_TERMS))
    119120            path.append(lookup_type) 
    120121            lookup_type = 'exact' 
     
    201202        # Does the name belong to a one-to-one, many-to-one, or regular field? 
    202203        field = find_field(name, current_opts.fields, False) 
     204 
    203205        if field: 
    204206            if field.rel: # One-to-One/Many-to-one field 
     
    294296            where.append(get_geo_where_clause(lookup_type, current_table + '.', column, value)) 
    295297        else: 
    296             raise TypeError, 'Field "%s" (%s) is not a Geometry Field.' % (column, field.__class__.__name__
     298            where.append(get_where_clause(lookup_type, current_table + '.', column, value)
    297299        params.extend(field.get_db_prep_lookup(lookup_type, value)) 
    298300 
    299301    return joins, where, params 
    300  
  • django/branches/gis/django/contrib/gis/db/models/query.py

    r4787 r4884  
    1 from django.db.models.query import * 
    2 from django.contrib.gis.db.models.postgis import geo_parse_lookup 
     1from django.db.models.query import Q, QNot, QuerySet 
     2from django.contrib.gis.db.models.postgis import parse_lookup 
     3import operator 
    34 
    45class GeoQ(Q): 
     
    67 
    78    def get_sql(self, opts): 
    8         "Overloaded to use the geo_parse_lookup() function instead of parse_lookup()
    9         return geo_parse_lookup(self.kwargs.items(), opts) 
     9        "Overloaded to use our own parse_lookup() function.
     10        return parse_lookup(self.kwargs.items(), opts) 
    1011 
    1112class GeoQuerySet(QuerySet): 
    1213    "Geographical-enabled QuerySet object." 
    1314 
    14     def geo_filter(self, *args, **kwargs): 
    15         "Returns a new GeoQuerySet instance with the args ANDed to the existing set." 
    16         return self._geo_filter_or_exclude(None, *args, **kwargs) 
     15    def __init__(self, model=None): 
     16        super(GeoQuerySet, self).__init__(model=model) 
    1717 
    18     def geo_exclude(self, *args, **kwargs): 
    19         "Returns a new GeoQuerySet instance with NOT (args) ANDed to the existing set." 
    20         return self._geo_filter_or_exclude(QNot, *args, **kwargs) 
     18        # We only want to use the GeoQ object for our queries 
     19        self._filters = GeoQ() 
    2120 
    22     def _geo_filter_or_exclude(self, mapper, *args, **kwargs): 
     21    def _filter_or_exclude(self, mapper, *args, **kwargs): 
    2322        # mapper is a callable used to transform Q objects, 
    2423        # or None for identity transform