Before we can store geographic information about or query for an object we have to know what we’re storing or querying by.
So what do we choose?
If we’re storing the location of an object, a models.PointField is your best bet. Could it be a three-dimensional models.MultiPolygonField? Sure. But I doubt your average user wants to go to that extent of effort. Thanks to geocoding (a topic for another day) we can translate their street address into a point with little effort.
If we’re storing political or geographic boundaries, models.MultiPolygonField is our best bet. Whether it’s a US State, county, time zone or country of the world it’s very likely the source data will be of this type.
If you really don’t know, and want to be lazy, there is models.GeometryCollectionField – the NoSQL of geographic fields. Sure you don’t have to tell anybody what you’re going to put there, but good luck finding what you need when it comes time to retrieve. The fields are fine, I hold no grudges against them – I just prefer to store my data more strongly typed.
Below are two snippets from different projects, both defining geographic models. One comes from my geodjango-uscampgrounds app and the other from my geodjango-tigerline app. Note we kill off the old-faithful “from django.db import models” in favor of “from django.contrib.gis.db import models” in order to have the geo fields available. We then override the default manager with a geospatially-aware one through “objects = models.GeoManager()” which is sort of optional, but you should know that if you ever attempt to do a geo query, or join from non-geospatial model to a geospatial one and try to do a geo query, it’s not going to work. You’re far better off just setting it on all models in the project whether they’re geographic or not now while you remember.
Note the PointField() definition has a kwarg you’ve likely not seen before – srid=4326. What is this? It’s a spatial reference system. I’m not going to explain it because I always have to look them up. And while that would shame any real geographer, it doesn’t shame me nor should it you. If you need to look one up, spatialreference.org is a great (and Django powered!) resource for you. If the data is coming from the TIGER/Line, a GPS receiver, or most anything else, it’s 4326 aka WGS 84 which is the GeoDjango default. I include it on my models just because.
from django.conf import settingsfrom django.contrib.gis.db import models
class Campground(models.Model):campground_code = models.CharField(max_length=64)name = models.CharField(max_length=128)campground_type = models.CharField(max_length=128)phone = models.CharField(max_length=128)comments = models.TextField()sites = models.CharField(max_length=128)elevation = models.CharField(max_length=128)hookups = models.CharField(max_length=128)amenities = models.TextField()point = models.PointField(srid=4326)
objects = models.GeoManager()
def __unicode__(self):return self.name
class Zipcode(models.Model):code = models.CharField(max_length=5)mpoly = models.MultiPolygonField()
objects = models.GeoManager()
def __unicode__(self):return self.code
Tomorrow we’ll start putting data in these models and continue down the road of getting geospatial information back from the database.