Django

Code

Changeset 7456

Show
Ignore:
Timestamp:
04/24/08 18:01:04 (2 months ago)
Author:
jbronn
Message:

gis: Fixed bug where extra parameters were passed into SQL for dwithin lookups for geodetic fields; now degree values (no Distance objects) may be used with dwithin lookups.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/db/backend/postgis/query.py

    r7104 r7456  
    229229                op = op(value[1]) 
    230230            elif lookup_type in DISTANCE_FUNCTIONS and lookup_type != 'dwithin': 
    231                 if field._unit_name == 'degree'
     231                if field.geodetic
    232232                    # Geodetic distances are only availble from Points to PointFields. 
    233233                    if field._geom != 'POINT': 
  • django/branches/gis/django/contrib/gis/db/models/fields/__init__.py

    r7138 r7456  
    8080 
    8181    ### Routines specific to GeometryField ### 
    82     def get_distance(self, dist): 
     82    @property 
     83    def geodetic(self): 
     84        return self._unit_name in self.geodetic_units 
     85 
     86    def get_distance(self, dist, lookup_type): 
    8387        """ 
    8488        Returns a distance number in units of the field.  For example, if  
     
    8690        then 1000 would be returned. 
    8791        """ 
    88          
     92        postgis = SpatialBackend.name == 'postgis' 
    8993        if isinstance(dist, Distance): 
    90             if self._unit_name in self.geodetic_units: 
     94            if self.geodetic: 
     95                # Won't allow Distance objects w/DWithin lookups on PostGIS. 
     96                if postgis and lookup_type == 'dwithin': 
     97                    raise TypeError('Only numeric values of degree units are allowed on geographic DWithin queries.') 
    9198                # Spherical distance calculation parameter should be in meters. 
    9299                dist_param = dist.m 
     
    98105 
    99106        # Sphereical distance query; returning meters. 
    100         if SpatialBackend.name == 'postgis' and self._unit_name in self.geodetic_units
     107        if postgis and self.geodetic and lookup_type != 'dwithin'
    101108            return [gqn(self._spheroid), dist_param] 
    102109        else: 
     
    171178                if lookup_type in SpatialBackend.distance_functions: 
    172179                    # Getting the distance parameter in the units of the field. 
    173                     where += self.get_distance(value[1]
     180                    where += self.get_distance(value[1], lookup_type
    174181                elif lookup_type in SpatialBackend.limited_where: 
    175182                    pass 
  • django/branches/gis/django/contrib/gis/tests/distapp/tests.py

    r7138 r7456  
    1818    # w/units in meters) 
    1919    stx_pnt = GEOSGeometry('POINT (-95.370401017314293 29.704867409475465)', 4326) 
    20      
     20    # Another one for Australia 
     21    au_pnt = GEOSGeometry('POINT (150.791 -34.4919)', 4326) 
     22 
    2123    def get_cities(self, qs): 
    2224        cities = [c.name for c in qs] 
     
    4446        for dist in dists: 
    4547            qs = SouthTexasCity.objects.filter(point__dwithin=(self.stx_pnt, dist)) 
    46             cities = self.get_cities(qs) 
    47             self.assertEqual(cities, ['Downtown Houston', 'Southside Place']) 
     48            self.assertEqual(['Downtown Houston', 'Southside Place'], self.get_cities(qs)) 
     49 
     50            if isinstance(dist, D): 
     51                # A TypeError should be raised when trying to pass Distance objects 
     52                # into a DWithin query using a geodetic field. 
     53                qs = AustraliaCity.objects.filter(point__dwithin=(self.au_pnt, dist)) 
     54                self.assertRaises(TypeError, qs.count) 
     55            else: 
     56                # Actually using a distance value of 0.5 degrees. 
     57                qs = AustraliaCity.objects.filter(point__dwithin=(self.au_pnt, 0.5)).order_by('name') 
     58                self.assertEqual(['Mittagong', 'Shellharbour', 'Thirroul', 'Wollongong'], self.get_cities(qs)) 
    4859 
    4960    def test03_distance_aggregate(self):