Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a big interrogation about how it could be possible to have a GeoDjango app that can store in database the uploaded shapefiles (or other geospatial files) from users. When you load shapefiles in GeoDjango, you have to create a new model that matches the fields of the shapefile. How could it be possible to create a new model automatically each time a user uploads a files? You can't append the new model definition to your each time? For me, that does not make any sense.

Does it means the best way is to use a generic model definition and only allow files upload that match this definition,and then to create a new instance of this generic model? Can someone explain me what is the best practice to create an app that can store users uploaded spatial files?

share|improve this question
up vote 4 down vote accepted

You are right, adding a new model to 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

share|improve this answer
you can combine django-hstore backend with geodjango backend easily: follow this!topic/django-users/… . The problem with this kind of generic models is the slowness when you upload table with many features. You can also take a look at dynamic models. – Below the Radar Jun 1 '13 at 14:19
Thank you for your answer! However, I think that the real solution for this issue is not yet created. We need a plugin in geodjango that will connect to uploaded tables in database maybe without model definition. – Below the Radar Jun 1 '13 at 14:36
Seeing that this question has recieved some interest lately I just want to point out that PostgreSQL now supports schemaless data, using json or hstore ( – atlefren Nov 17 '15 at 10:06
That's great! Would you prefer hstore or json tought? – Below the Radar Nov 18 '15 at 19:55
I think the Layermapping module will help reduce overhead here: – sal May 3 at 9:51

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.