I'm developing a geospatial mapping application using geodjango
and django-leaflet
which lets users draw a polygon on a map and save that polygon to a model. I thought it would be simple to extract the saved polygon from the model and render it on a Leaflet map embedded in a template. However, I'm having considerable difficulty doing so. This is mostly due to me being a new web developer (I'm especially new to JS). Here's what I have so far:
models.py:
class newJob(BaseModel):
job_name = models.CharField(max_length=64)
job_desc = models.CharField(max_length=64)
job_loc = models.PolygonField()
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
The spatial data is saved successfully to the model using the form I have created (not shown). I have then created a simple function-based view to pull the required data from the database. I have created a 'raw' object (job_loc
) and also serialized the data to geojson to create json_loc
(as I'm not sure which is best to work with).
views.py:
def viewjob(request):
req = request.GET
job_name = newJob.objects.values_list('job_name', flat=True).get(pk=req['search'])
job_desc = newJob.objects.values_list('job_desc', flat=True).get(pk=req['search'])
job_loc = newJob.objects.values_list('job_loc', flat=True).get(pk=req['search'])
json_loc = newJob.objects.filter(pk=req['search'])
json_loc = serialize('geojson', json_loc, geometry_field='job_loc')
context = {
'job_name': job_name,
'job_desc': job_desc,
'job_loc': job_loc,
'json_loc': json_loc
}
print(context)
return render(request,'viewjob.html', context)
And the code in my template. I was hoping that I could pass job_loc
or json_loc
to leaflet
and be done with it (given everything I'm working with is geospatial), but that's clearly not the case.
{{ json_loc }}
{{job_loc}}
<script type="text/javascript">
function map_init(map, options) {
// zoom to point
map.setView([51.9923, -2.1580], 12);
// get polygon
var polygon = "{{ json_loc }}";
var polygon = L.polygon(polygon).addTo(map);
}
</script>
{% leaflet_map "yourmap" callback="window.map_init_basic" %}
Here is a screenshot if I render the above code (might be helpful to see the data that's returned from json_loc
and job_loc
, respectively):
I've heard that Ajax might be a potential solution here, but I'm unsure on how to implement this. I was expecting to load the data into the map directly without using an Ajax call (i.e. the polygon is passed from the view on page render, then inserted into the map directly).
Can anyone guide me on the best way to acomplish this?
It turns out the solution was very straightforward with the use of Django GeoJSON. Using Django GeoJSON, there's no need to mess around with serialising the polygon data in your view.
Simply pass the raw spatial data from your database into views.py and then into your template like so:
def index(request):
req = request.GET
job_loc = yourModel.objects.values_list('location', flat=True).get(pk=req['search'])
context = {
'job_loc': job_loc,
}
return render(request,'app/viewjob.html', context)
And then in your template {% load geojson_tags %}
:
<script type="text/javascript">
function map_init(map, options) {
map.setView([51.9923, -0.5], 7);
L.geoJson({{ job_loc|geojsonfeature|safe}}).addTo(map);
}
</script>