Just change
cities = City.objects.filter(location__within=boundaries)
To
cities = City.objects.filter(location__within=boundaries).distance(centre).order_by('distance')
Each City object will also have a 'distance' attribute.
You are right, adding a new model to models.py each time is impossible. And, if it where, you would end up with a lot of unmanageable tables.
One option is to use a schema-less datastore (i.e. a NoSQL database) but then you'd loose the spaial capabilities of PostGIS (or have to use both PostGIS and a NoSQL db, no fun!). And then there's the concept of "hstore" in PostgreSQL which allows you to store a set of key/value pairs in a single column. Unfortunately, the django-hstore lib requires its own db.backend definition, this would result in a conflict with the geodjango-backend.
This means that the solution I would recommend is one described in the book "Python Geospatial Development". I'll just outline the approach here, either you get the idea or you could get yourself a copy of the book for a more thourough explaination.
In brief:
Model your app like this:
class Shapefile(models.Model):
filename = models.CharField(max_length=255)
srs = models.CharField(max_length=255)
geom_type = models.CharField(max_length=50)
encoding = models.CharField(max_length=20)
class Attribute(models.Model):
shapefile = models.ForeignKey(Shapefile)
name = models.CharField(max_length=255)
type = models.IntegerField()
width = models.IntegerField()
precision = models.IntegerField()
class Feature(models.Model):
shapefile = models.ForeignKey(Shapefile)
geom_point = models.PointField(srid=4326, blank=True, null=true)
geom_multipoint = models.MultiPointField(srid=4326, blank=True, null=true)
geom_multilinestring = models.MultiLineStringField(srid=4326, blank=True, null=true)
geom_multipolygon = models.MultiPolygonField(srid=4326, blank=True, null=true)
geom_geometrycollection = models.GeometryCollectionField(srid=4326, blank=True, null=true)
objects = models.GeoManager()
class AttributeValue(models.Model):
feature = models.ForeignKey(Feature)
attribute = models.ForeignKey(Attribute)
value = models.CharField(max_length=255, blank=True, null=true)
In this way the shapefile schema is modeled in a set of relations
Best Answer
I ended up solving this by overriding the admin model in admin.py, and setting the latitude/longitude fields as read-only like this:
I then modified the relevant model in my models.py to override the save function so that it assigned the longitude and latitude fields from the PointField.