10

I set up a model with models.PolygonField in geodjango, using postgres as database. I try to import shp into postgres. The problem is, shp (compiled with QGIS) mixes polygon and multipolygon, hence it always fails to do the export because of the constraint check enforce_geotype.

Is there a way to clear the constraint, so as to store both multipolygon and polygon type data?

3 Answers 3

11

The SQL to drop the constraint:

ALTER TABLE myapp_mymodel DROP CONSTRAINT enforce_geotype_mygeom;

Or to alter it to allow both Polygons & MultiPolygons:

ALTER TABLE myapp_mymodel DROP CONSTRAINT enforce_geotype_mygeom;
ALTER TABLE myapp_mymodel ADD CONSTRAINT enforce_geotype_mygeom CHECK (geometrytype(mygeom) = 'POLYGON'::text OR geometrytype(mygeom) = 'MULTIPOLYGON'::text OR mygeom IS NULL);

These SQL statements could be run from a South migration or an initial-data SQL script.

Another option is to make it a GeometryField in your Django model definition - this will allow it to store any geometry type.

Or, override the save() method on your model to force everything to be a MultiPolygon:

from django.contrib.gis.db import models
from django.contrib.gis import geos

class MyModel(models.Model):
  mygeom = models.MultiPolygonField()
  ... other fields....

  def save(self, *args, **kwargs):
    # if mygeom ends up as a Polgon, make it into a MultiPolygon
    if self.mygeom and isinstance(self.mygeom, geos.Polygon):
      self.mygeom = geos.MultiPolygon(self.mygeom)

    super(MyModel).save(*args, **kwargs)
1
  • 1
    The last method might be a good choice
    – ChanDon
    Sep 7, 2011 at 3:02
6

I know this is old, but I just ran into this issue myself and had problems using the above suggested solutions:

  • Using GeometryField makes it difficult to use the built-in OSMGeoAdmin class. The code in templates/gis/admin/openlayers.js (and contrib/gis/admin/widgets.py and probably other places I missed) frequently assumes that the geometry is a point, line, polygon, or collection, and never accounts for generic geometries. This isn't necessarily important or insurmountable, but if you were planning on using the built-in admin you might be disappointed.

  • Overriding save() doesn't work because the type-checking happens sooner, in the model's __set__().

My current solution is explicitly coercing all of my Polygons into MultiPolygons when importing and saving my data. I might override __set__() if this becomes cumbersome.

6

longish workaround

one could use fromstr()

from django.contrib.gis.geos import fromstr

p = Polygon()
# this seems to work correctly
mp = MultiPolygon(fromstr(str(p)),)

model1.geom_field = mp

model1.save()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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