django - 将 GeoDjango 查询集发送到模板并使用 OpenLayers.js 进行使用

标签 django openlayers gis geodjango

我最近一直在学习使用 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 &copy; 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/

相关文章:

python - 从 django-notifications-hq 序列化 NotificationQuerySet 不起作用

ajax - 当缩放更改时,如何使用 OpenLayers 中止未完成的 map 图 block 请求?

r - 使用行/列索引对栅格进行子集

map - 如何计算 map 上的线段交点

java - 使用JAVA中的geotools在定义的距离(km)内从一条线(GPS坐标)生成多边形

django usercreationform is_valid 总是返回 false

django - 如何在 Django 夹具中引用内容类型?

python - 升级 pip/安装 django - [SSL : TLSV1_ALERT_PROTOCOL_VERSION]

java android openlayers 等效

javascript - insertXY() 到新草图 - Openlayers