2014-01-08 58 views
3

我最近一直在学习使用GeoDjango,并且我一直在通过一些教程来尝试了解如何将所有内容放在一起。我也是GIS新手,但对Django比较舒服。GeoDjango查询集对象

我已明确了沿着这个教程,如果不是有点过时,这是伟大如下: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); 

我写了以下ng代码,但我不断收到错误信息(js console)“Object has not method'replace'”。

我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属性?我已经看到了如何通过使用返回静态文件的视图/ url来实现这一点,但我希望能够通过直接向模板返回数据来实现这一点。

脚注:我已经看到一些其他答案,说使用vectorformats,但它似乎应该有一种方式来在GeoDjango本地做到这一点,但与我的谷歌搜索和寻找答案,我似乎无法找到了解人们通常如何做到这一点。

感谢您的帮助。

编辑:

我觉得有点愚蠢,但@ sk1p问我关于JS回溯,当我看着它,它告诉我,负责该错误的行为以下几点:

map.zoomToMaxExtent(countryson.geometry.getBounds()); 

所以我删除它,错误消失,但我仍然无法让我的地图渲染。我将继续查看返回的对象。

+0

究竟是什么问题? – sk1p

+0

'输入'键使它快速发布。编辑完整的问题。 – erewok

+0

你能获得该js错误的回溯吗?另外,看看生成的html/js:IIRC'.geojson'不会返回完整的GeoJSON对象,您可能需要查看OpenLayers API以查看它是否接受您传递的内容 – sk1p

回答

3

经过大量实验后,我找到了一个可以在模板中渲染geojson的系统。我认为我的错误是非常基本的,并且来自不了解实际几何字段本身必须呈现为geojson(并且可以从模板访问)。

我也切换到使用Leaflet,因为它加载非常快,它似乎有一个很好的API。

我有一个导入shapefile并将它们分解为Shapefile-> Features-> Attributes的程序。这受Python for Geo-Spatial Development一书的启发。相关型号如下:

models.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) 

:因为我处理通用shape文件,我不知道以前的功能会有什么样的几何形状,我已经包括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) 

我的模板使用单张处理返回的对象,像这样:

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 %} 
} 

我不知道这是否会成为其他人的帮助,并有可能是更好的方法来做到这一点,特别是在我试图找出用来居中我的地图的经纬度时。