Skip to content

Commit 82b2580

Browse files
committed
[soc2009/admin-ui] Merging trunk r10924 into my branch.
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/admin-ui@10925 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 6275888 commit 82b2580

File tree

24 files changed

+1308
-478
lines changed

24 files changed

+1308
-478
lines changed
3.73 KB
Binary file not shown.

django/conf/locale/es_AR/LC_MESSAGES/django.po

Lines changed: 499 additions & 275 deletions
Large diffs are not rendered by default.

django/contrib/gis/db/models/sql/where.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def add(self, data, connector):
3535
return super(WhereNode, self).add(data, connector)
3636

3737
obj, lookup_type, value = data
38-
alias, col, field = obj.alias, obj.col, obj.field
38+
col, field = obj.col, obj.field
3939

4040
if not hasattr(field, "geom_type"):
4141
# Not a geographic field, so call `WhereNode.add`.
@@ -76,7 +76,7 @@ def add(self, data, connector):
7676
# the `get_geo_where_clause` to construct the appropriate
7777
# spatial SQL when `make_atom` is called.
7878
annotation = GeoAnnotation(field, value, where)
79-
return super(WhereNode, self).add(((alias, col, field.db_type()), lookup_type, annotation, params), connector)
79+
return super(WhereNode, self).add(((obj.alias, col, field.db_type()), lookup_type, annotation, params), connector)
8080

8181
def make_atom(self, child, qn):
8282
obj, lookup_type, value_annot, params = child

django/contrib/gis/maps/google/gmap.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def xhtml(self):
143143
@property
144144
def icons(self):
145145
"Returns a sequence of GIcon objects in this map."
146-
return [marker.icon for marker in self.markers if marker.icon]
146+
return set([marker.icon for marker in self.markers if marker.icon])
147147

148148
class GoogleMapSet(GoogleMap):
149149

@@ -221,6 +221,6 @@ def onload(self):
221221
@property
222222
def icons(self):
223223
"Returns a sequence of all icons in each map of the set."
224-
icons = []
225-
for map in self.maps: icons.extend(map.icons)
224+
icons = set()
225+
for map in self.maps: icons |= map.icons
226226
return icons

django/contrib/gis/maps/google/overlays.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,14 @@ def __init__(self, varname, image=None, iconsize=None,
231231
self.iconanchor = iconanchor
232232
self.infowindowanchor = infowindowanchor
233233

234+
def __cmp__(self, other):
235+
return cmp(self.varname, other.varname)
236+
237+
def __hash__(self):
238+
# XOR with hash of GIcon type so that hash('varname') won't
239+
# equal hash(GIcon('varname')).
240+
return hash(self.__class__) ^ hash(self.varname)
241+
234242
class GMarker(GOverlayBase):
235243
"""
236244
A Python wrapper for the Google GMarker object. For more information

django/contrib/gis/tests/relatedapp/models.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,13 @@ class Parcel(models.Model):
3232
border2 = models.PolygonField(srid=2276)
3333
objects = models.GeoManager()
3434
def __unicode__(self): return self.name
35+
36+
# These use the GeoManager but do not have any geographic fields.
37+
class Author(models.Model):
38+
name = models.CharField(max_length=100)
39+
objects = models.GeoManager()
40+
41+
class Book(models.Model):
42+
title = models.CharField(max_length=100)
43+
author = models.ForeignKey(Author, related_name='books')
44+
objects = models.GeoManager()

django/contrib/gis/tests/relatedapp/tests.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import os, unittest
22
from django.contrib.gis.geos import *
33
from django.contrib.gis.db.backend import SpatialBackend
4-
from django.contrib.gis.db.models import F, Extent, Union
4+
from django.contrib.gis.db.models import Count, Extent, F, Union
55
from django.contrib.gis.tests.utils import no_mysql, no_oracle, no_spatialite
66
from django.conf import settings
7-
from models import City, Location, DirectoryEntry, Parcel
7+
from models import City, Location, DirectoryEntry, Parcel, Book, Author
88

99
cities = (('Aurora', 'TX', -97.516111, 33.058333),
1010
('Roswell', 'NM', -104.528056, 33.387222),
@@ -196,8 +196,8 @@ def test09_pk_relations(self):
196196
# ID values do not match their City ID values.
197197
loc1 = Location.objects.create(point='POINT (-95.363151 29.763374)')
198198
loc2 = Location.objects.create(point='POINT (-96.801611 32.782057)')
199-
dallas = City.objects.create(name='Dallas', location=loc2)
200-
houston = City.objects.create(name='Houston', location=loc1)
199+
dallas = City.objects.create(name='Dallas', state='TX', location=loc2)
200+
houston = City.objects.create(name='Houston', state='TX', location=loc1)
201201

202202
# The expected ID values -- notice the last two location IDs
203203
# are out of order. We want to make sure that the related
@@ -231,6 +231,32 @@ def test11_geoquery_pickle(self):
231231
q = pickle.loads(q_str)
232232
self.assertEqual(GeoQuery, q.__class__)
233233

234+
def test12_count(self):
235+
"Testing `Count` aggregate use with the `GeoManager`. See #11087."
236+
# Creating a new City, 'Fort Worth', that uses the same location
237+
# as Dallas.
238+
dallas = City.objects.get(name='Dallas')
239+
ftworth = City.objects.create(name='Fort Worth', state='TX', location=dallas.location)
240+
241+
# Count annotation should be 2 for the Dallas location now.
242+
loc = Location.objects.annotate(num_cities=Count('city')).get(id=dallas.location.id)
243+
self.assertEqual(2, loc.num_cities)
244+
245+
# Creating some data for the Book/Author non-geo models that
246+
# use GeoManager. See #11087.
247+
tp = Author.objects.create(name='Trevor Paglen')
248+
Book.objects.create(title='Torture Taxi', author=tp)
249+
Book.objects.create(title='I Could Tell You But Then You Would Have to be Destroyed by Me', author=tp)
250+
Book.objects.create(title='Blank Spots on the Map', author=tp)
251+
wp = Author.objects.create(name='William Patry')
252+
Book.objects.create(title='Patry on Copyright', author=wp)
253+
254+
# Should only be one author (Trevor Paglen) returned by this query, and
255+
# the annotation should have 3 for the number of books.
256+
qs = Author.objects.annotate(num_books=Count('books')).filter(num_books__gt=1)
257+
self.assertEqual(1, len(qs))
258+
self.assertEqual(3, qs[0].num_books)
259+
234260
# TODO: Related tests for KML, GML, and distance lookups.
235261

236262
def suite():

django/contrib/gis/utils/ogrinspect.py

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212

1313
def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False):
1414
"""
15-
Given a DataSource, generates a dictionary that may be used
15+
Given a DataSource, generates a dictionary that may be used
1616
for invoking the LayerMapping utility.
1717
1818
Keyword Arguments:
1919
`geom_name` => The name of the geometry field to use for the model.
20-
20+
2121
`layer_key` => The key for specifying which layer in the DataSource to use;
2222
defaults to 0 (the first layer). May be an integer index or a string
2323
identifier for the layer.
@@ -31,7 +31,7 @@ def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False):
3131
pass
3232
else:
3333
raise TypeError('Data source parameter must be a string or a DataSource object.')
34-
34+
3535
# Creating the dictionary.
3636
_mapping = {}
3737

@@ -52,32 +52,32 @@ def ogrinspect(*args, **kwargs):
5252
model name this function will generate a GeoDjango model.
5353
5454
Usage:
55-
55+
5656
>>> from django.contrib.gis.utils import ogrinspect
5757
>>> ogrinspect('/path/to/shapefile.shp','NewModel')
58-
58+
5959
...will print model definition to stout
60-
60+
6161
or put this in a python script and use to redirect the output to a new
6262
model like:
63-
63+
6464
$ python generate_model.py > myapp/models.py
65-
66-
# generate_model.py
65+
66+
# generate_model.py
6767
from django.contrib.gis.utils import ogrinspect
6868
shp_file = 'data/mapping_hacks/world_borders.shp'
6969
model_name = 'WorldBorders'
7070
7171
print ogrinspect(shp_file, model_name, multi_geom=True, srid=4326,
7272
geom_name='shapes', blank=True)
73-
73+
7474
Required Arguments
7575
`datasource` => string or DataSource object to file pointer
76-
76+
7777
`model name` => string of name of new model class to create
78-
78+
7979
Optional Keyword Arguments
80-
`geom_name` => For specifying the model name for the Geometry Field.
80+
`geom_name` => For specifying the model name for the Geometry Field.
8181
Otherwise will default to `geom`
8282
8383
`layer_key` => The key for specifying which layer in the DataSource to use;
@@ -86,38 +86,38 @@ def ogrinspect(*args, **kwargs):
8686
8787
`srid` => The SRID to use for the Geometry Field. If it can be determined,
8888
the SRID of the datasource is used.
89-
89+
9090
`multi_geom` => Boolean (default: False) - specify as multigeometry.
91-
91+
9292
`name_field` => String - specifies a field name to return for the
9393
`__unicode__` function (which will be generated if specified).
94-
95-
`imports` => Boolean (default: True) - set to False to omit the
96-
`from django.contrib.gis.db import models` code from the
94+
95+
`imports` => Boolean (default: True) - set to False to omit the
96+
`from django.contrib.gis.db import models` code from the
9797
autogenerated models thus avoiding duplicated imports when building
9898
more than one model by batching ogrinspect()
99-
99+
100100
`decimal` => Boolean or sequence (default: False). When set to True
101101
all generated model fields corresponding to the `OFTReal` type will
102102
be `DecimalField` instead of `FloatField`. A sequence of specific
103103
field names to generate as `DecimalField` may also be used.
104104
105105
`blank` => Boolean or sequence (default: False). When set to True all
106-
generated model fields will have `blank=True`. If the user wants to
106+
generated model fields will have `blank=True`. If the user wants to
107107
give specific fields to have blank, then a list/tuple of OGR field
108108
names may be used.
109109
110110
`null` => Boolean (default: False) - When set to True all generated
111111
model fields will have `null=True`. If the user wants to specify
112112
give specific fields to have null, then a list/tuple of OGR field
113113
names may be used.
114-
114+
115115
Note: This routine calls the _ogrinspect() helper to do the heavy lifting.
116116
"""
117117
return '\n'.join(s for s in _ogrinspect(*args, **kwargs))
118118

119119
def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=None,
120-
multi_geom=False, name_field=None, imports=True,
120+
multi_geom=False, name_field=None, imports=True,
121121
decimal=False, blank=False, null=False):
122122
"""
123123
Helper routine for `ogrinspect` that generates GeoDjango models corresponding
@@ -140,7 +140,7 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non
140140
# keyword arguments.
141141
def process_kwarg(kwarg):
142142
if isinstance(kwarg, (list, tuple)):
143-
return [s.lower() for s in kwarg]
143+
return [s.lower() for s in kwarg]
144144
elif kwarg:
145145
return [s.lower() for s in ogr_fields]
146146
else:
@@ -164,18 +164,18 @@ def get_kwargs_str(field_name):
164164
yield ''
165165

166166
yield 'class %s(models.Model):' % model_name
167-
167+
168168
for field_name, width, precision, field_type in izip(ogr_fields, layer.field_widths, layer.field_precisions, layer.field_types):
169169
# The model field name.
170170
mfield = field_name.lower()
171171
if mfield[-1:] == '_': mfield += 'field'
172-
172+
173173
# Getting the keyword args string.
174174
kwargs_str = get_kwargs_str(field_name)
175175

176176
if field_type is OFTReal:
177177
# By default OFTReals are mapped to `FloatField`, however, they
178-
# may also be mapped to `DecimalField` if specified in the
178+
# may also be mapped to `DecimalField` if specified in the
179179
# `decimal` keyword.
180180
if field_name.lower() in decimal_fields:
181181
yield ' %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)' % (mfield, width, precision, kwargs_str)
@@ -192,8 +192,8 @@ def get_kwargs_str(field_name):
192192
elif field_type is OFTDate:
193193
yield ' %s = models.TimeField(%s)' % (mfield, kwargs_str[2:])
194194
else:
195-
raise TypeError('Unknown field type %s in %s' % (fld_type, mfield))
196-
195+
raise TypeError('Unknown field type %s in %s' % (field_type, mfield))
196+
197197
# TODO: Autodetection of multigeometry types (see #7218).
198198
gtype = layer.geom_type
199199
if multi_geom and gtype.num in (1, 2, 3):

0 commit comments

Comments
 (0)