问题
I have a geodjango queryset containing several fields but want to use only user_name
and location
(a point field) which I want to use as a marker in google maps API 3.
Bear with me as I don’t know Javascript and I have a series of questions.
Take this as conceptual brainstorming for a novice:
My SO search suggests that I need to serialize the queryset objects to JSON. I use the built-in serializer module to convert to JSON.
I think the JSON objects are converted inviews.py
(let’s call itjson_data
). Are these JSON objects stored in the PostGIS database? Wouldn’t that be redundant?Furthermore, how do I reference them in the
map.js
(google maps API 3) javascript file?
I want to (import?link?) JSON objects to display them as location markers.I want to know how to declare and iterate the javascript variable
locations
.
For var(i=0;i< locations.length;i++){[
[json_data.user_name, json_data.point],
]
var map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(49.279504, -123.1162),
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var marker, i;
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
map: map,
icon: 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png'
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(locations[i][0]);
infowindow.open(map, marker);
}
})(marker, i));
}
Guide me if I went unnecessarily convoluted way to do a simple task.
回答1:
TL;DR
- No, what you are doing is not redundant and nothing get's written to the database from those answers.
- You need to make a
getJSON()
or similar call to your API's endpoint to access the data. - You can do it on the 2nd step's call and declare it as a list.
What you are thinking is pretty much correct but there is room for improvement (thus the long answer below).
Answer:
Some time ago I read a very good initiation tutorial on building a GIS application with geodjango and google maps. Read it and it should give you a great jump start.
After you read that we will follow a somewhat different way which leaves more room to play around with your front-end (use react for example or whatever comes to mind).
The back-end:
Create a view to retrieve the information you want (
user_name
,location
) as JSON, using the values() queryset method which returns a list of dictionaries.
Since we have to JSONify a list, we will use JsonResponse and we will mark it as unsafe:from django.http import JsonResponse def my_view(request): resp = MyModel.objects.all().values('user_name', 'location') return JsonResponse(list(resp), safe=False)
Add an endpoint to access that view on
urls.py
:urlpatterns = [ ... url(r'^my_endpoint/$', my_view, name='my_endpoint'), ... ]
Now whenever we access the
my_endpoint/
we will get a JSON representation of every object'suser_name
andlocation
in our database which will look like this:[ {user_name: a_user, location: [lat, lng]}, {user_name: another_user, location: [lat, lng]}, ... ]
Moving to the front-end now:
Make a
getJSON()
or anajax()
or any other type of call to the API and in the same time create a marker list (close to what @MoshFeu suggests):let map = new google.maps.Map(document.getElementById('map'), { center: new google.maps.LatLng(49.279504, -123.1162), zoom: 14, mapTypeId: google.maps.MapTypeId.ROADMAP }); let markers = []; $.getJSON( "my_base_url/my_endpoint", function(data) { $.each(data, function() { markers.push( new google.maps.Marker({ position: { lat: data['location'][0], lng: data['location'][1] }, map: map, icon: 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png' }) ); }); }); ...
And we are pretty much done!
You don't need to make any special serialization to your data.
You can query the data from any type of front-end you can imagine which gives you designing freedom.
回答2:
My use-case. I used django.contrib.gis
(django.contrib.gis.db.models.PolygonField
) and needed to replace default map with Google maps + change default map coordinates, zoom, etc.
TL;DR
- I created a new app called
gis_addons
with custom template and widget to use. - I instructed my model admin (using
formfield_overrides
) to use my own map widget.
Make sure to add the gis_addons
to INSTALLED_APPS
.
File: gis_addons/templates/gis_addons/openlayers_googlemaps.html
{% extends "gis/openlayers.html" %}
{% load i18n l10n %}
{% block base_layer %}
var base_layer = new ol.layer.Tile({
source: new ol.source.XYZ({
attributions: [new ol.Attribution({ html: '<a href=""></a>' })],
maxZoom: 25,
url: "http://mt0.google.com/vt/lyrs=r&hl=en&x={x}&y={y}&z={z}&s=Ga"
})
});
{% endblock %}
{% block options %}var options = {
base_layer: base_layer,
geom_name: '{{ geom_type }}',
id: '{{ id }}',
map_id: '{{ id }}_map',
map_options: map_options,
map_srid: {{ map_srid|unlocalize }},
name: '{{ name }}',
default_lat: 53.2193835,
default_lon: 6.5665018,
default_zoom: 15
};
{% endblock %}
File: gis_addons/widgets.py
from django.contrib.gis.forms.widgets import OpenLayersWidget
class GoogleMapsOpenLayersWidget(OpenLayersWidget):
"""Google Maps OpenLayer widget."""
template_name = 'gis_addons/openlayers_googlemaps.html'
File: my_app/models.py
from django.db import models
from django.contrib.gis.db import models as gis_models
from django.utils.translation import ugettext_lazy as _
class MyModel(models.Model):
# ...
coordinates = gis_models.PolygonField(
verbose_name=_("Geo coordinates"),
)
def __str__(self):
return self.name
File: my_app/admin.py
from django.contrib import admin
from django.contrib.gis.db.models import PolygonField
from gis_addons.widgets import GoogleMapsOpenLayersWidget
from my_app.models import MyModel
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
# ...
formfield_overrides = {
PolygonField: {"widget": GoogleMapsOpenLayersWidget}
}
来源:https://stackoverflow.com/questions/45985408/how-to-integrate-geodjango-with-google-maps-api-3