我最近一直在学习使用 GeoDjango,并且一直在学习一些教程来尝试了解所有内容是如何组合在一起的。我也是 GIS 新手,但对 Django 比较熟悉。
我一直在特别关注本教程,即使不是有点过时,也很棒:https://code.google.com/p/geodjango-basic-apps/wiki/FOSS4GWorkshop
我已经完成了第 8 部分,尽我所能更新了 django 的内容,并尝试绕过已弃用的 OpenLayers 内容,但我遇到了一些问题。
本教程包含以下代码,用于生成查询集并将其发送到由 OpenLayers.js 使用的模板:
教程的 view.py:
def ward(request, id):
ward = get_object_or_404(Ward, pk=id)
interesting_points = InterestingLocation.objects.filter(
geometry__intersects=(ward.geometry))
return render_to_response("ward.html", {
'ward': ward, 'interesting_points': interesting_points })
教程的 OpenLayers 代码(不完整):
geojson_format = new OpenLayers.Format.GeoJSON()
ward = geojson_format.read({{ ward.geometry.geojson|safe}})[0];
// We mark it 'safe' so that Django doesn't escape the quotes.
ward.attributes = { 'name': "{{ward.name}}", 'type': 'ward'};
vectors = new OpenLayers.Layer.Vector("Data");
vectors.addFeatures(ward);
我编写了以下代码,但我不断收到错误消息(js 控制台)“对象没有方法‘替换’”。
我的view.py
def interesting_area(request, iso3_id):
iso3_id = iso3_id.upper()
country = get_object_or_404(WorldBorder, iso3=iso3_id)
interesting_points = InterestingLocation.objects.filter(
geometry__intersects=(country.mpoly))
return render_to_response("some_places.html", {
'country': country,
'interesting_points': interesting_points})
我的 openlayers.js 尝试
function map_init() {
json_format = new OpenLayers.Format.GeoJSON();
countryson = json_format.read({{country.mpoly.geojson|safe}})[0];
countryson.attributes = {'name': "{{country.name}}",
'area': "{{country.area}}",
'population': "{{country.pop2005}}",
'type': 'country'};
vectors = new OpenLayers.Layer.Vector("Data");
vectors.addFeatures(countryson);
var map = new OpenLayers.Map('map-container');
var base_layer = new OpenLayers.Layer.OSM("Base Map", {
"tileOptions": { "crossOriginKeyword": null }
});
map.addLayers([base_layer, vectors]);
map.zoomToMaxExtent(countryson.geometry.getBounds());
}
我相信错误出现在行 countryson = json_format.read({{country.mpoly.geojson|safe}})[0];
有谁知道如何发送模型对象并能够在模板端读取其geometry.geojson属性?我已经了解了如何通过使用返回静态文件的 View /url 来做到这一点,但我希望能够通过将数据直接返回到模板来做到这一点。
脚注:我看到了一些其他答案说使用矢量格式,但似乎应该有一种方法可以在 GeoDjango 中本地执行此操作,但通过我的谷歌搜索和搜索答案,我似乎无法找到答案人们通常如何做到这一点。
感谢您的帮助。
编辑:
我觉得有点愚蠢,但是@sk1p向我询问了js回溯,当我查看它时,它告诉我导致错误的行如下:
map.zoomToMaxExtent(countryson.geometry.getBounds());
所以我删除了它,错误消失了,但我仍然无法渲染我的 map 。我将继续查看返回的对象。
最佳答案
经过大量实验,我找到了一个可以在模板中渲染 geojson 的系统。我认为我的错误非常基本,来自于不理解实际的几何字段本身必须呈现为 geojson (并且可以从模板访问)。
我还转而使用 Leaflet,因为它加载速度非常快,而且它似乎有一个很好的 API。
我有一个程序可以导入 shapefile 并将它们分解为 Shapefile->Features->Attributes。这是受到《Python for Geo-Spatial Development》一书的启发。相关模型如下:
模型.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)
注意:因为我正在处理通用形状文件,并且我之前不知道这些特征将具有什么样的几何形状,所以我在要返回的特征上包含了 geometry
属性实际的几何字段并丢弃其他未使用的字段。稍后我会使用它从模板内访问几何图形的 geojson 方法。
在我看来,我会响应包含 shapefile ID 的请求,并查询该 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)
我的模板使用 Leaflet 来处理返回的对象,如下所示:
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 %}
}
我不确定这对其他人是否有帮助,并且可能有更好的方法来做到这一点,特别是当我试图找出用于使 map 居中的纬度和经度时。
关于django - 将 GeoDjango 查询集发送到模板并使用 OpenLayers.js 进行使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20985259/