如何将 Geodjango 与 Google 地图 API 3 集成?
How to integrate Geodjango with Google Maps API 3?
我有一个包含多个字段的 geodjango 查询集,但只想使用 user_name
和 location
(一个点字段),我想将它们用作 google 地图中的标记 API 3.
请耐心等待,因为我不知道 Javascript,我有一系列问题。
以此作为新手的概念头脑风暴:
我的 SO 搜索提示我需要序列化查询集对象
到 JSON。我使用内置的序列化器模块转换为 JSON。
我认为 JSON 对象在 views.py
中转换(让我们
称之为 json_data
)。这些 JSON 对象是否存储在 PostGIS 数据库中?这不是多余的吗?
此外,我如何在 map.js
(google 地图中引用它们
API 3) javascript 文件?
我想(导入?link?)JSON 对象将它们显示为位置标记。
我想知道如何声明和迭代javascript变量
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));
}
如果我以不必要的复杂方式完成简单任务,请指导我。
TL;DR
- 不,您所做的并不是多余的,这些答案中没有任何内容写入数据库。
- 您需要对 API 的端点进行
getJSON()
或类似调用才能访问数据。
- 您可以在第 2 步的调用中执行此操作并将其声明为列表。
您的想法基本正确,但还有改进的余地(因此下面的答案很长)。
答案:
前段时间看了一篇very good initiation tutorial on building a GIS application with geodjango and google maps。阅读它,它应该会给你一个很好的开始。
在您阅读之后,我们将采用一种稍微不同的方式,为您的前端留出更多空间(例如,使用 React 或任何想到的方式)。
后端:
使用 values()
查询集方法 JSON 创建视图以检索所需信息(user_name
、location
)returns 字典列表。
由于我们必须 JSON 验证一个列表,我们将使用 JsonResponse
并将其标记为不安全:
from django.http import JsonResponse
def my_view(request):
resp = MyModel.objects.all().values('user_name', 'location')
return JsonResponse(list(resp), safe=False)
添加端点以访问 urls.py
上的该视图:
urlpatterns = [
...
url(r'^my_endpoint/$', my_view, name='my_endpoint'),
...
]
现在,每当我们访问 my_endpoint/
时,我们都会得到数据库中每个对象的 user_name
和 location
的 JSON 表示,如下所示:
[
{user_name: a_user, location: [lat, lng]},
{user_name: another_user, location: [lat, lng]},
...
]
现在转到前端:
对 API 进行 getJSON()
或 ajax()
或任何其他类型的调用,同时创建一个标记列表(接近什么@MoshFeu 建议):
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'
})
);
});
});
...
我们差不多完成了!
您不需要对您的数据进行任何特殊的序列化。
您可以从您能想到的任何类型的前端查询数据,这为您提供了设计自由。
我的用例。我使用 django.contrib.gis
(django.contrib.gis.db.models.PolygonField
) 并需要用 Google 地图替换默认地图 + 更改默认地图坐标、缩放等
TL;DR
- 我创建了一个名为
gis_addons
的新应用,其中包含要使用的自定义模板和小部件。
- 我指示我的模型管理员(使用
formfield_overrides
)使用我自己的地图小部件。
确保将 gis_addons
添加到 INSTALLED_APPS
。
文件: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 %}
文件: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'
文件: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
文件: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}
}
我有一个包含多个字段的 geodjango 查询集,但只想使用 user_name
和 location
(一个点字段),我想将它们用作 google 地图中的标记 API 3.
请耐心等待,因为我不知道 Javascript,我有一系列问题。
以此作为新手的概念头脑风暴:
我的 SO 搜索提示我需要序列化查询集对象 到 JSON。我使用内置的序列化器模块转换为 JSON。
我认为 JSON 对象在views.py
中转换(让我们 称之为json_data
)。这些 JSON 对象是否存储在 PostGIS 数据库中?这不是多余的吗?此外,我如何在
map.js
(google 地图中引用它们 API 3) javascript 文件?
我想(导入?link?)JSON 对象将它们显示为位置标记。我想知道如何声明和迭代javascript变量
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));
}
如果我以不必要的复杂方式完成简单任务,请指导我。
TL;DR
- 不,您所做的并不是多余的,这些答案中没有任何内容写入数据库。
- 您需要对 API 的端点进行
getJSON()
或类似调用才能访问数据。 - 您可以在第 2 步的调用中执行此操作并将其声明为列表。
您的想法基本正确,但还有改进的余地(因此下面的答案很长)。
答案:
前段时间看了一篇very good initiation tutorial on building a GIS application with geodjango and google maps。阅读它,它应该会给你一个很好的开始。
在您阅读之后,我们将采用一种稍微不同的方式,为您的前端留出更多空间(例如,使用 React 或任何想到的方式)。
后端:
使用
values()
查询集方法 JSON 创建视图以检索所需信息(user_name
、location
)returns 字典列表。
由于我们必须 JSON 验证一个列表,我们将使用JsonResponse
并将其标记为不安全:from django.http import JsonResponse def my_view(request): resp = MyModel.objects.all().values('user_name', 'location') return JsonResponse(list(resp), safe=False)
添加端点以访问
urls.py
上的该视图:urlpatterns = [ ... url(r'^my_endpoint/$', my_view, name='my_endpoint'), ... ]
现在,每当我们访问
my_endpoint/
时,我们都会得到数据库中每个对象的user_name
和location
的 JSON 表示,如下所示:[ {user_name: a_user, location: [lat, lng]}, {user_name: another_user, location: [lat, lng]}, ... ]
现在转到前端:
对 API 进行
getJSON()
或ajax()
或任何其他类型的调用,同时创建一个标记列表(接近什么@MoshFeu 建议):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' }) ); }); }); ...
我们差不多完成了!
您不需要对您的数据进行任何特殊的序列化。
您可以从您能想到的任何类型的前端查询数据,这为您提供了设计自由。
我的用例。我使用 django.contrib.gis
(django.contrib.gis.db.models.PolygonField
) 并需要用 Google 地图替换默认地图 + 更改默认地图坐标、缩放等
TL;DR
- 我创建了一个名为
gis_addons
的新应用,其中包含要使用的自定义模板和小部件。 - 我指示我的模型管理员(使用
formfield_overrides
)使用我自己的地图小部件。
确保将 gis_addons
添加到 INSTALLED_APPS
。
文件: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 %}
文件: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'
文件: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
文件: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}
}