More

Displaying PostgGIS geometry on GeoDjango map widget?


I'm trying to display a custom map feature on a GeoDjango map. The geometry is a multipolygon stored in a PostGIS database backend.

And I have trouble to find the correct piece of documentation that explains how to load and add my geometry from the database. This is what my PostGIS contains:

SELECT * FROM aptroomat_worldborder;

This is mymodel.pyequivalent in my GeoDjango project:

from django.contrib.gis.db import models class WorldBorder(models.Model): name = models.CharField(max_length=50) area = models.IntegerField() pop2005 = models.IntegerField('Population 2005') fips = models.CharField('FIPS Code', max_length=2) iso2 = models.CharField('2 Digit ISO', max_length=2) iso3 = models.CharField('3 Digit ISO', max_length=3) un = models.IntegerField('United Nations Code') region = models.IntegerField('Region Code') subregion = models.IntegerField('Sub-Region Code') lon = models.FloatField() lat = models.FloatField() mpoly = models.MultiPolygonField() objects = models.GeoManager() def __str__(self): return self.name

This is how I define my form informs.py:

from django.contrib.gis import forms class WorldBorderForm(forms.Form): world = forms.MultiPolygonField(widget = forms.OSMWidget(attrs = {'map_width': 1024, 'map_height': 600}))

And myviews.pycontaining the callback:

from django.shortcuts import render from myproject.forms import WorldBorderForm def index(request): form = WorldBorderForm() context = { 'form': form } return render(request, 'myproject/index.html', context)

This is how the result looks including my template, using an OSM base widget:

This is pretty much what I get from reading the GeoDjango documentation and following the GeoDjango tutorial on World Borders.

But the missing piece in the docs is: How to display my geometries from the PostGIS database in my GeoDjango map widget? I can't seem to figure out how to connect both.

Any ideas?

Source code is on github.com/donSchoe/sabracta.

Versions used in this project are:

  • python 3.4.3
  • postgresql 9.4.1
  • postgis 2.1.5
  • django 1.7.4

If you want to display your shapefiles on the map canvas, it can be done by creating .kml files.

First in models.py create functions to convert data to .kml:

def shpPoint(request): points = ShapefilePoint.objects.kml() return render_to_kml("placemarks.kml", {'places': points})

placemarks.kml is a simple template for that purpose, it can be found in geodjango documentation I guess:

{% extends "base.kml" %} {% block placemarks %}{% for place in places %}  {% if place.name %}{{ place.name }}{% else %}{{ place }}{% endif %} {% if place.description %}{{ place.description }}{% else %}{{ place }}{% endif %} {{ place.kml|safe }} {% endfor %}{% endblock %}

and function to rendering:

def index(request): return render_to_response("map.html")

Now map your kml link in urls.py:

… url(r'^point/', shpPoint),…

And finally you can add your layer in JS code (this code contains example styling for point layer):

var PointLayer = new ol.layer.Vector({ title: 'Point', source: new ol.source.KML({ projection:new ol.proj.get("EPSG:3857"), url:'http://localhost:8000/point/', extractStyles: false }), style: (function() { var textStroke = new ol.style.Stroke({ color: 'yellow', width: 3 }); var textFill = new ol.style.Fill({ color: 'black' }); return function(feature, resolution) { return [new ol.style.Style({ image: new ol.style.Circle({ radius: 7, fill: new ol.style.Fill({color: 'yellow'}), stroke: new ol.style.Stroke({color: 'red'}) }), text: new ol.style.Text({ font: '11px arial,sans-serif', text: feature.get('name'), fill: textFill, stroke: textStroke, offsetX: 25, offsetY: -10 }) })]; }; })() }); map.addLayer(PointLayer);

Take a look at this tutorial using Leaflet instead of OpenLayers. It worked for me and the docs and plugins are great. The GeoDjango tutorial does fall short for displaying maps.


Watch the video: Installing PostgreSQL and PostGIS Part1 Best GeoDjango Tutorial (October 2021).