3👍
After a lot of experimentation, I found a system that works to render geojson in the template. I think my error was pretty elementary and came from not understanding that the actual geometry field itself must be rendered as geojson (and this can be accessed from the template).
I also switched to using Leaflet because it loaded really quickly and it seems to have a nice API.
I have a program which imports shapefiles and breaks them up into Shapefile->Features->Attributes. This is inspired by the book Python for Geo-Spatial Development. The relevant models looks like this:
models.py:
class Shapefile(models.Model):
filename = models.CharField(max_length=255)
srs_wkt = models.TextField()
geom_type = models.CharField(max_length=50)
class Feature(models.Model):
shapefile = models.ForeignKey(Shapefile)
reference = models.CharField(max_length=100, blank=True)
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()
def __str__(self):
return "{}".format(self.id)
## need some method to return the geometry type this guy has.
def _get_geometry(self):
geoms = [self.geom_point, self.geom_multipoint,
self.geom_multilinestring, self.geom_multipolygon,
self.geom_geometrycollection]
geom = next(filter(lambda x: x, geoms))
return geom
geometry = property(_get_geometry)
Note: because I am processing generic shapefiles and I do not previously know what kind of geometries the features will have, I have included geometry
property on the feature to return the actual geometry field and discard the other unused ones. I use this later on to access the geometry’s geojson method from within the template.
In my view, I respond to requests that include a shapefile id with a query on the features in that shapefile.
views.py:
def view_shapefile(request, shapefile_id,
template_file='shape_editor/viewshapefile.html'):
all_features = Feature.objects.filter(
shapefile__id=shapefile_id).select_related(
'shapefile')
filename = all_features[0].shapefile.filename
### we need something to set the center of our map ###
lon, lat = all_features[0].geometry.centroid.tuple
temp_vars = {'features' : all_features,
'filename' : filename,
'lon': lon,
'lat' : lat}
return render(request, template_file, temp_vars)
And my template uses Leaflet to process the returned objects like so:
function map_init(map_div) {
var tileMapQuest = L.tileLayer('http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png', {
subdomains: ['otile1','otile2','otile3','otile4'],
attribution: 'Map tiles by <a href="http://open.mapquestapi.com/">MapQuest</a>. Data © by <a href="http://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>.',
maxZoom: 18
});
var map_layers = [tileMapQuest];
var map = L.map('map-container', {
center: [{{ lat }}, {{ lon }}],
zoom: 10,
layers: map_layers,
worldCopyJump: false
});
{% if features %}
{% for feat in features %}
var feature = new L.geoJson({{ feat.geometry.geojson|safe }}).addTo(map);
{% endfor %}
{% endif %}
}
I am not sure if that will be helpful for anyone else, and there are probably better ways to do it, particularly where I’m trying to figure out the latitude and longitude to use to center my maps.