Changeset 7836 for django/branches/gis/django/contrib
- Timestamp:
- 07/04/08 15:16:22 (5 months ago)
- Files:
-
- django/branches/gis (modified) (1 prop)
- django/branches/gis/django/contrib/auth/backends.py (modified) (4 diffs)
- django/branches/gis/django/contrib/auth/fixtures (copied) (copied from django/trunk/django/contrib/auth/fixtures)
- django/branches/gis/django/contrib/auth/fixtures/authtestdata.json (copied) (copied from django/trunk/django/contrib/auth/fixtures/authtestdata.json)
- django/branches/gis/django/contrib/auth/models.py (modified) (3 diffs)
- django/branches/gis/django/contrib/auth/tests.py (modified) (2 diffs)
- django/branches/gis/django/contrib/auth/urls.py (copied) (copied from django/trunk/django/contrib/auth/urls.py)
- django/branches/gis/django/contrib/flatpages/models.py (modified) (1 diff)
- django/branches/gis/django/contrib/formtools/tests.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/db/backend/mysql/query.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/db/backend/oracle/query.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/db/backend/postgis/query.py (modified) (4 diffs)
- django/branches/gis/django/contrib/gis/db/models/fields/__init__.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/db/models/sql/query.py (modified) (4 diffs)
- django/branches/gis/django/contrib/gis/db/models/sql/where.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/tests/distapp/tests.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/tests/geoapp/tests.py (modified) (9 diffs)
- django/branches/gis/django/contrib/sitemaps/management (copied) (copied from django/trunk/django/contrib/sitemaps/management)
- django/branches/gis/django/contrib/sitemaps/management/commands (copied) (copied from django/trunk/django/contrib/sitemaps/management/commands)
- django/branches/gis/django/contrib/sitemaps/management/commands/ping_google.py (copied) (copied from django/trunk/django/contrib/sitemaps/management/commands/ping_google.py)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis
- Property svnmerge-integrated changed from /django/trunk:1-7767 to /django/trunk:1-7835
django/branches/gis/django/contrib/auth/backends.py
r7279 r7836 1 try: 2 set 3 except NameError: 4 from sets import Set as set # Python 2.3 fallback 5 1 6 from django.db import connection 2 7 from django.contrib.auth.models import User 3 8 4 try: 5 set 6 except NameError: 7 from sets import Set as set # Python 2.3 fallback 8 9 9 10 class ModelBackend(object): 10 11 """ 11 Authenticate against django.contrib.auth.models.User12 Authenticates against django.contrib.auth.models.User. 12 13 """ 13 14 # TODO: Model, login attribute name and password attribute name should be … … 22 23 23 24 def get_group_permissions(self, user_obj): 24 "Returns a list of permission strings that this user has through his/her groups." 25 """ 26 Returns a set of permission strings that this user has through his/her 27 groups. 28 """ 25 29 if not hasattr(user_obj, '_group_perm_cache'): 26 30 cursor = connection.cursor() … … 51 55 user_obj._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()]) 52 56 return user_obj._group_perm_cache 53 57 54 58 def get_all_permissions(self, user_obj): 55 59 if not hasattr(user_obj, '_perm_cache'): … … 62 66 63 67 def has_module_perms(self, user_obj, app_label): 64 return bool(len([p for p in self.get_all_permissions(user_obj) if p[:p.index('.')] == app_label])) 68 """ 69 Returns True if user_obj has any permissions in the given app_label. 70 """ 71 for perm in self.get_all_permissions(user_obj): 72 if perm[:perm.index('.')] == app_label: 73 return True 74 return False 65 75 66 76 def get_user(self, user_id): django/branches/gis/django/contrib/auth/models.py
r7642 r7836 97 97 verbose_name = _('group') 98 98 verbose_name_plural = _('groups') 99 ordering = ('name',)100 99 101 100 class Admin: 102 101 search_fields = ('name',) 102 ordering = ('name',) 103 103 104 104 def __unicode__(self): … … 154 154 verbose_name = _('user') 155 155 verbose_name_plural = _('users') 156 ordering = ('username',)157 156 158 157 class Admin: … … 167 166 list_filter = ('is_staff', 'is_superuser') 168 167 search_fields = ('username', 'first_name', 'last_name', 'email') 168 ordering = ('username',) 169 169 170 170 def __unicode__(self): django/branches/gis/django/contrib/auth/tests.py
r7642 r7836 1 1 """ 2 >>> from models import User, AnonymousUser2 >>> from django.contrib.auth.models import User, AnonymousUser 3 3 >>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw') 4 4 >>> u.has_usable_password() … … 54 54 u'!' 55 55 """ 56 57 from django.test import TestCase 58 from django.core import mail 59 60 class PasswordResetTest(TestCase): 61 fixtures = ['authtestdata.json'] 62 urls = 'django.contrib.auth.urls' 63 def test_email_not_found(self): 64 "Error is raised if the provided email address isn't currently registered" 65 response = self.client.get('/password_reset/') 66 self.assertEquals(response.status_code, 200) 67 response = self.client.post('/password_reset/', {'email': 'not_a_real_email@email.com'}) 68 self.assertContains(response, "That e-mail address doesn't have an associated user account") 69 self.assertEquals(len(mail.outbox), 0) 70 71 def test_email_found(self): 72 "Email is sent if a valid email address is provided for password reset" 73 response = self.client.post('/password_reset/', {'email': 'staffmember@example.com'}) 74 self.assertEquals(response.status_code, 302) 75 self.assertEquals(len(mail.outbox), 1) django/branches/gis/django/contrib/flatpages/models.py
r7768 r7836 9 9 help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes.")) 10 10 title = models.CharField(_('title'), max_length=200) 11 content = models.TextField(_('content') )11 content = models.TextField(_('content'), blank=True) 12 12 enable_comments = models.BooleanField(_('enable comments')) 13 13 template_name = models.CharField(_('template name'), max_length=70, blank=True, django/branches/gis/django/contrib/formtools/tests.py
r7768 r7836 22 22 23 23 class PreviewTests(TestCase): 24 urls = 'django.contrib.formtools.test_urls' 24 25 25 26 def setUp(self): 26 self._old_root_urlconf = settings.ROOT_URLCONF27 settings.ROOT_URLCONF = 'django.contrib.formtools.test_urls'28 27 # Create a FormPreview instance to share between tests 29 28 self.preview = preview.FormPreview(TestForm) … … 31 30 self.input = input_template % (self.preview.unused_name('stage'), "%d") 32 31 33 def tearDown(self):34 settings.ROOT_URLCONF = self._old_root_urlconf35 36 32 def test_unused_name(self): 37 33 """ django/branches/gis/django/contrib/gis/db/backend/mysql/query.py
r7699 r7836 39 39 MYSQL_GIS_TERMS = MYSQL_GIS_FUNCTIONS.keys() 40 40 MYSQL_GIS_TERMS += MISC_TERMS 41 MYSQL_GIS_TERMS = tuple(MYSQL_GIS_TERMS) # Making immutable41 MYSQL_GIS_TERMS = dict((term, None) for term in MYSQL_GIS_TERMS) # Making dictionary 42 42 43 def get_geo_where_clause( lookup_type, table_prefix, field, value):43 def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 44 44 "Returns the SQL WHERE clause for use in MySQL spatial SQL construction." 45 45 # Getting the quoted field as `geo_col`. 46 geo_col = '%s.%s' % (qn(table_ prefix), qn(field.column))46 geo_col = '%s.%s' % (qn(table_alias), qn(name)) 47 47 48 48 # See if a MySQL Geometry function matches the lookup type next … … 55 55 # geometries in its spatial indices. 56 56 if lookup_type == 'isnull': 57 return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or ''))57 return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 58 58 59 59 raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) django/branches/gis/django/contrib/gis/db/backend/oracle/query.py
r7641 r7836 111 111 112 112 #### The `get_geo_where_clause` function for Oracle #### 113 def get_geo_where_clause( lookup_type, table_prefix, field, value):113 def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 114 114 "Returns the SQL WHERE clause for use in Oracle spatial SQL construction." 115 115 # Getting the quoted table name as `geo_col`. 116 geo_col = '%s.%s' % (qn(table_ prefix), qn(field.column))116 geo_col = '%s.%s' % (qn(table_alias), qn(name)) 117 117 118 118 # See if a Oracle Geometry function matches the lookup type next … … 127 127 128 128 # Ensuring that a tuple _value_ was passed in from the user 129 if not isinstance( value, tuple):129 if not isinstance(geo_annot.value, tuple): 130 130 raise TypeError('Tuple required for `%s` lookup type.' % lookup_type) 131 if len( value) != 2:131 if len(geo_annot.value) != 2: 132 132 raise ValueError('2-element tuple required for %s lookup type.' % lookup_type) 133 133 134 134 # Ensuring the argument type matches what we expect. 135 if not isinstance( value[1], arg_type):136 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type( value[1])))135 if not isinstance(geo_annot.value[1], arg_type): 136 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type(geo_annot.value[1]))) 137 137 138 138 if lookup_type == 'relate': 139 139 # The SDORelate class handles construction for these queries, 140 140 # and verifies the mask argument. 141 return sdo_op( value[1]).as_sql(geo_col)141 return sdo_op(geo_annot.value[1]).as_sql(geo_col) 142 142 else: 143 143 # Otherwise, just call the `as_sql` method on the SDOOperation instance. … … 150 150 elif lookup_type == 'isnull': 151 151 # Handling 'isnull' lookup type 152 return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or ''))152 return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 153 153 154 154 raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) django/branches/gis/django/contrib/gis/db/backend/postgis/query.py
r7641 r7836 219 219 POSTGIS_TERMS += POSTGIS_GEOMETRY_FUNCTIONS.keys() # Adding on the Geometry Functions 220 220 POSTGIS_TERMS += MISC_TERMS # Adding any other miscellaneous terms (e.g., 'isnull') 221 POSTGIS_TERMS = tuple(POSTGIS_TERMS) # Making immutable221 POSTGIS_TERMS = dict((term, None) for term in POSTGIS_TERMS) # Making a dictionary for fast lookups 222 222 223 223 # For checking tuple parameters -- not very pretty but gets job done. … … 229 229 230 230 #### The `get_geo_where_clause` function for PostGIS. #### 231 def get_geo_where_clause( lookup_type, table_prefix, field, value):231 def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 232 232 "Returns the SQL WHERE clause for use in PostGIS SQL construction." 233 233 # Getting the quoted field as `geo_col`. 234 geo_col = '%s.%s' % (qn(table_ prefix), qn(field.column))234 geo_col = '%s.%s' % (qn(table_alias), qn(name)) 235 235 if lookup_type in POSTGIS_OPERATORS: 236 236 # See if a PostGIS operator matches the lookup type. … … 249 249 250 250 # Ensuring that a tuple _value_ was passed in from the user 251 if not isinstance( value, (tuple, list)):251 if not isinstance(geo_annot.value, (tuple, list)): 252 252 raise TypeError('Tuple required for `%s` lookup type.' % lookup_type) 253 253 254 # Number of valid tuple parameters depends on the lookup type. 254 nparams = len( value)255 nparams = len(geo_annot.value) 255 256 if not num_params(lookup_type, nparams): 256 257 raise ValueError('Incorrect number of parameters given for `%s` lookup type.' % lookup_type) 257 258 258 259 # Ensuring the argument type matches what we expect. 259 if not isinstance( value[1], arg_type):260 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type( value[1])))260 if not isinstance(geo_annot.value[1], arg_type): 261 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type(geo_annot.value[1]))) 261 262 262 263 # For lookup type `relate`, the op instance is not yet created (has 263 264 # to be instantiated here to check the pattern parameter). 264 265 if lookup_type == 'relate': 265 op = op( value[1])266 op = op(geo_annot.value[1]) 266 267 elif lookup_type in DISTANCE_FUNCTIONS and lookup_type != 'dwithin': 267 if field.geodetic:268 if geo_annot.geodetic: 268 269 # Geodetic distances are only availble from Points to PointFields. 269 if field._geom!= 'POINT':270 if geo_annot.geom_type != 'POINT': 270 271 raise TypeError('PostGIS spherical operations are only valid on PointFields.') 271 if value[0].geom_typeid != 0:272 if geo_annot.value[0].geom_typeid != 0: 272 273 raise TypeError('PostGIS geometry distance parameter is required to be of type Point.') 273 274 # Setting up the geodetic operation appropriately. 274 if nparams == 3 and value[2] == 'spheroid': op = op[2]275 if nparams == 3 and geo_annot.value[2] == 'spheroid': op = op[2] 275 276 else: op = op[1] 276 277 else: … … 282 283 elif lookup_type == 'isnull': 283 284 # Handling 'isnull' lookup type 284 return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or ''))285 return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 285 286 286 287 raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) django/branches/gis/django/contrib/gis/db/models/fields/__init__.py
r7641 r7836 112 112 raise ValueError('Could not create geometry from lookup value: %s' % str(value)) 113 113 else: 114 raise TypeError('Cannot use parameter of `%s` type as lookup parameter.' % type(value))114 raise TypeError('Cannot use parameter of `%s` type as a geometry lookup parameter.' % type(value)) 115 115 116 116 # Assigning the SRID value. django/branches/gis/django/contrib/gis/db/models/sql/query.py
r7699 r7836 104 104 return result 105 105 106 def get_default_columns(self, with_aliases=False, col_aliases=None): 106 def get_default_columns(self, with_aliases=False, col_aliases=None, 107 start_alias=None, opts=None, as_pairs=False): 107 108 """ 108 109 Computes the default columns for selecting every field in the base … … 116 117 """ 117 118 result = [] 118 table_alias = self.tables[0] 119 if opts is None: 120 opts = self.model._meta 121 if start_alias: 122 table_alias = start_alias 123 else: 124 table_alias = self.tables[0] 119 125 root_pk = self.model._meta.pk.column 120 126 seen = {None: table_alias} 121 qn = self.quote_name_unless_alias122 qn2 = self.connection.ops.quote_name123 127 aliases = set() 124 128 for field, model in self.model._meta.get_fields_with_model(): … … 129 133 root_pk, model._meta.pk.column)) 130 134 seen[model] = alias 131 135 if as_pairs: 136 result.append((alias, field.column)) 137 continue 132 138 # This part of the function is customized for GeoQuery. We 133 139 # see if there was any custom selection specified in the 134 140 # dictionary, and set up the selection format appropriately. 135 141 field_sel = self.get_field_select(field, alias) 136 137 142 if with_aliases and field.column in col_aliases: 138 143 c_alias = 'Col%d' % len(col_aliases) … … 146 151 if with_aliases: 147 152 col_aliases.add(field.column) 153 if as_pairs: 154 return result, None 148 155 return result, aliases 149 156 django/branches/gis/django/contrib/gis/db/models/sql/where.py
r7641 r7836 1 import datetime 2 from django.db.models.fields import Field 1 3 from django.db.models.sql.where import WhereNode 2 4 from django.contrib.gis.db.backend import get_geo_where_clause, SpatialBackend 3 5 6 class GeoAnnotation(object): 7 """ 8 The annotation used for GeometryFields; basically a placeholder 9 for metadata needed by the `get_geo_where_clause` of the spatial 10 backend. 11 """ 12 def __init__(self, field, value, where): 13 self.geodetic = field.geodetic 14 self.geom_type = field._geom 15 self.value = value 16 self.where = tuple(where) 17 4 18 class GeoWhereNode(WhereNode): 5 19 """ 6 The GeoWhereNode calls the `get_geo_where_clause` from the appropriate7 spatial backend in order to construct correct spatial SQL.20 Used to represent the SQL where-clause for spatial databases -- 21 these are tied to the GeoQuery class that created it. 8 22 """ 23 def add(self, data, connector): 24 """ 25 This is overridden from the regular WhereNode to handle the 26 peculiarties of GeometryFields, because they need a special 27 annotation object that contains the spatial metadata from the 28 field so that the correct spatial SQL is generated. 29 """ 30 if not isinstance(data, (list, tuple)): 31 super(WhereNode, self).add(data, connector) 32 return 33 34 alias, col, field, lookup_type, value = data 35 # Do we have a geographic field? 36 geo_field = hasattr(field, '_geom') 37 if field: 38 if geo_field: 39 # `GeometryField.get_db_prep_lookup` returns a where clause 40 # substitution array in addition to the parameters. 41 where, params = field.get_db_prep_lookup(lookup_type, value) 42 else: 43 params = field.get_db_prep_lookup(lookup_type, value) 44 db_type = field.db_type() 45 else: 46 # This is possible when we add a comparison to NULL sometimes (we 47 # don't really need to waste time looking up the associated field 48 # object). 49 params = Field().get_db_prep_lookup(lookup_type, value) 50 db_type = None 51 52 if geo_field: 53 # The annotation will be a `GeoAnnotation` object that 54 # will contain the necessary geometry field metadata for 55 # the `get_geo_where_clause` to construct the appropriate 56 # spatial SQL when `make_atom` is called. 57 annotation = GeoAnnotation(field, value, where) 58 elif isinstance(value, datetime.datetime): 59 annotation = datetime.datetime 60 else: 61 annotation = bool(value) 62 63 super(WhereNode, self).add((alias, col, db_type, lookup_type, 64 annotation, params), connector) 65 9 66 def make_atom(self, child, qn): 10 table_alias, name, field, lookup_type, value = child 11 if hasattr(field, '_geom'): 67 table_alias, name, db_type, lookup_type, value_annot, params = child 68 69 if isinstance(value_annot, GeoAnnotation): 12 70 if lookup_type in SpatialBackend.gis_terms: 13 71 # Getting the geographic where clause; substitution parameters 14 72 # will be populated in the GeoFieldSQL object returned by the 15 73 # GeometryField. 16 gwc = get_geo_where_clause(lookup_type, table_alias, field, value) 17 where, params = field.get_db_prep_lookup(lookup_type, value) 18 return gwc % tuple(where), params 74 gwc = get_geo_where_clause(table_alias, name, lookup_type, value_annot) 75 return gwc % value_annot.where, params 19 76 else: 20 77 raise TypeError('Invalid lookup type: %r' % lookup_type) django/branches/gis/django/contrib/gis/tests/distapp/tests.py
r7666 r7836 89 89 90 90 # Creating the query set. 91 qs = AustraliaCity.objects. filter(point__dwithin=(self.au_pnt, dist)).order_by('name')91 qs = AustraliaCity.objects.order_by('name') 92 92 if type_error: 93 93 # A TypeError should be raised on PostGIS when trying to pass 94 94 # Distance objects into a DWithin query using a geodetic field. 95 self.assertRaises(TypeError, qs.count)95 self.assertRaises(TypeError, AustraliaCity.objects.filter, point__dwithin=(self.au_pnt, dist)) 96 96 else: 97 self.assertEqual(au_cities, self.get_names(qs ))98 97 self.assertEqual(au_cities, self.get_names(qs.filter(point__dwithin=(self.au_pnt, dist)))) 98 99 99 def test03a_distance_method(self): 100 100 "Testing the `distance` GeoQuerySet method on projected coordinate systems." … … 218 218 # Too many params (4 in this case) should raise a ValueError. 219 219 self.assertRaises(ValueError, 220 AustraliaCity.objects.filter (point__distance_lte=('POINT(5 23)', D(km=100), 'spheroid', '4')).count)220 AustraliaCity.objects.filter, point__distance_lte=('POINT(5 23)', D(km=100), 'spheroid', '4')) 221 221 222 222 # Not enough params should raise a ValueError. 223 223 self.assertRaises(ValueError, 224 AustraliaCity.objects.filter (point__distance_lte=('POINT(5 23)',)).count)224 AustraliaCity.objects.filter, point__distance_lte=('POINT(5 23)',)) 225 225 226 226 # Getting all cities w/in 550 miles of Hobart. django/branches/gis/django/contrib/gis/tests/geoapp/tests.py
r7699 r7836 199 199 def test06_make_line(self): 200 200 "Testing the `make_line` GeoQuerySet method." 201 if DISABLE: return 201 202 # Ensuring that a `TypeError` is raised on models without PointFields. 202 203 self.assertRaises(TypeError, State.objects.make_line) … … 382 383 pnt2 = fromstr('POINT(-98.4919715741052 29.4333344025053)', srid=4326) 383 384 384 # Testing bad argument tuples that should return a TypeError or 385 # a ValueError. 386 bad_args = [((pnt1, 0), TypeError), 387 ((pnt2, 'T*T***FF*', 0), ValueError), 388 ((23, 'foo'), ValueError), 389 ] 390 for args, e in bad_args: 391 qs = Country.objects.filter(mpoly__relate=args) 385 # Not passing in a geometry as first param shoud 386 # raise a type error when initializing the GeoQuerySet 387 self.assertRaises(TypeError, Country.objects.filter, mpoly__relate=(23, 'foo')) 388 # Making sure the right exception is raised for the given 389 # bad arguments. 390 for bad_args, e in [((pnt1, 0), TypeError), ((pnt2, 'T*T***FF*', 0), ValueError)]: 391 qs = Country.objects.filter(mpoly__relate=bad_args) 392 392 self.assertRaises(e, qs.count) 393 393 … … 472 472 def test19_centroid(self): 473 473 "Testing the `centroid` GeoQuerySet method." 474 if DISABLE: return 474 475 qs = State.objects.exclude(poly__isnull=True).centroid() 475 476 if oracle: tol = 0.1 … … 480 481 def test20_pointonsurface(self): 481 482 "Testing the `point_on_surface` GeoQuerySet method." 483 if DISABLE: return 482 484 # Reference values. 483 485 if SpatialBackend.oracle: … … 498 500 def test21_scale(self): 499 501 "Testing the `scale` GeoQuerySet method." 502 if DISABLE: return 500 503 xfac, yfac = 2, 3 501 504 qs = Country.objects.scale(xfac, yfac, model_att='scaled') … … 510 513 def test22_translate(self): 511 514 "Testing the `translate` GeoQuerySet method." 515 if DISABLE: return 512 516 xfac, yfac = 5, -23 513 517 qs = Country.objects.translate(xfac, yfac, model_att='translated') … … 521 525 def test23_numgeom(self): 522 526 "Testing the `num_geom` GeoQuerySet method." 527 if DISABLE: return 523 528 # Both 'countries' only have two geometries. 524 529 for c in Country.objects.num_geom(): self.assertEqual(2, c.num_geom) … … 531 536 def test24_numpoints(self): 532 537 "Testing the `num_points` GeoQuerySet method." 538 if DISABLE: return 533 539 for c in Country.objects.num_points(): self.assertEqual(c.mpoly.num_points, c.num_points) 534 540 if postgis: … … 539 545 def test25_geoset(self): 540 546 "Testing the `difference`, `intersection`, `sym_difference`, and `union` GeoQuerySet methods." 547 if DISABLE: return 541 548 geom = Point(5, 23) 542 549 for c in Country.objects.all().intersection(geom).difference(geom).sym_difference(geom).union(geom):
