如何使用视图从 PostGIS 中提取几何图形,然后使用 Django 将其添加到模板中的传单地图中

bla*_*ake 2 django geometry postgis geojson leaflet

我想在视图中使用 python 从 PostGIS 数据库中提取多边形几何数据,并将其添加到模板中的传单地图中。最简单的方法似乎是提取数据并使用 Django 视图中的 postgis 函数 ST_AsGeoJSON 将其转换为 GeoJSON,然后将其作为 L.geoJSON(GEOJSON).addTo(map) 函数中的上下文渲染到模板。

这是行不通的。在请求地图页面时,地图现在是空白的,并且似乎无法识别 GeoJSON。我已经能够从视图传递硬编码的多边形并将其添加到地图中,但我的 postgis 数据库中的几何数据根本无效。

这是一个带有硬编码多边形的视图,已成功打印在地图上:

from django.shortcuts import render

def map_view(request, *args, **kwargs):
    geo_json={
        "type": "FeatureCollection",
          "features": [
            {
              "type": "Feature",
              "properties": {},
              "geometry": {
                "type": "Polygon",
                "coordinates": [
                  [
                    [
                      -0.10746002197265625,
                      51.505537109466715
                    ],
                    [
                      -0.11466979980468751,
                      51.498377681772325
                    ],
                    [
                      -0.0968170166015625,
                      51.493568479510415
                    ],
                    [
                      -0.09080886840820312,
                      51.502438390761164
                    ],
                    [
                      -0.10746002197265625,
                      51.505537109466715
                    ]
                  ]
                ]
              }
            }
          ]
        }

    return render(request ,'map.html', {'geo_json': geo_json})

Run Code Online (Sandbox Code Playgroud)

地图模板如下所示:

<!DOCTYPE html>
<html>
<head>
    <title>Map Page</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
    <style>
        #map {  position: relative;
                width: 600px;
                height: 775px;
                border: 3px solid #000000;}
    </style>    
</head>
<body>
    <div id="map"></div>
    <script>
        var map = L.map('map').setView([54.8,-4.45],6);

        L.tileLayer('https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=9GKOA9jJ3jCIWFUd8k00', {attribution: '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>',}).addTo(map);

        L.geoJSON({{ geo_json | safe }}).addTo(map);

    </script>

</body>
</html>
Run Code Online (Sandbox Code Playgroud)

这是添加了多边形的传单地图

现在,当我尝试使用新视图从 postgis 数据库获取传递 GeoJSON 时,它不起作用:

import psycopg2
from django.shortcuts import render

def map_view(request, *args, **kwargs):

    connection = psycopg2.connect(database="electio5_geekdata",user="electio5_blake", password="dummypassword", host='localhost')
    cursor = connection.cursor()
    cursor.execute("select st_AsGeoJSON(shape) from boris_constituency limit 1")
    varpoly=cursor.fetchall()

    geo_json={
        "type": "FeatureCollection",
          "features": [
            {
              "type": "Feature",
              "properties": {},
              "geometry": varpoly
            }
          ]
        }

    return render(request ,'map.html', {'geo_json': geo_json})
Run Code Online (Sandbox Code Playgroud)

我注意到输出时 GeoJSON 的格式略有不同:-

很好

{'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'properties': {}, 'geometry': {'type': '多边形', '坐标' 等等很快

是一个问题

{'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'properties': {}, 'geometry': [('{"type":"MultiPolygon","坐标" and等等等等

有问题的 GeoJSON 在第二个“type”键之前有额外的括号和引号

所以我的问题是:-

1/ 是否可以重新格式化有问题的 GeoJSON?我很难去除列表中不需要的字符

2/ 或者我可以只提取坐标并将其传递给 geo_json 的相关部分吗?

3/或者我可以通过任何方式从postgis中提取多边形数据并将其添加到传单地图中

顺便说一句,您可能想知道为什么我使用游标而不是使用具有 GeoJSON 方法的 Django 模型对象。由于库配置不正确,这种方法给了我一个 GDAL 错误,这又是一个问题!

非常感谢您对此的关注。

菲尔#anoobintrouble

bla*_*ake 5

正如您将在上面的评论中看到的那样,“cabesuon”给了我答案。但我会整合所有内容,希望能帮助未来的用户。这是一种从 PostGIS 数据库中提取几何(多边形)数据,然后将其渲染到模板并使用 Django Web 框架将其添加到传单地图的方法。

下面的视图提取数据,将其转换为 GeoJSON,然后将其返回到 map.html 模板:-

from django.shortcuts import render
import json
import psycopg2

def map_view(request, *args, **kwargs):

    connection = psycopg2.connect(database="electio5_geekdata",user="electio5_blake", password="adummypassword", host='localhost')
    cursor = connection.cursor()
    cursor.execute("select name, st_AsGeoJSON(shape) from boris_constituency limit 1")

    varcons=cursor.fetchone()

    geo_json={
              "type": "Feature",
              "name": varcons[0],
              "properties": {},
              "geometry": json.loads(varcons[1])
            }

    return render(request ,'map.html', {'geo_json': geo_json})

Run Code Online (Sandbox Code Playgroud)

下面的地图模板选取​​ geo_json 上下文并将其添加到传单地图中,绘制多边形几何图形(在本例中是“Aldershot”的英国议会选区):-

<!DOCTYPE html>
<html>
<head>
    <title>Map Page</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
    <style>
        #map {  position: relative;
                width: 600px;
                height: 775px;
                border: 3px solid #000000;}
    </style>    
</head>
<body>
    <div id="map"></div>
    <script>
        var map = L.map('map').setView([54.8,-4.45],6);

        L.tileLayer('https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=9GKOA9jJ3jCIWFUd8k00', {attribution: '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>',}).addTo(map);

        L.geoJSON({{ geo_json | safe }}).addTo(map);

    </script>

    {{ geo_json }}

</body>
</html>
Run Code Online (Sandbox Code Playgroud)

这是地图上绘制的几何图形

一些注意事项:-

1/我使用纯python来访问数据库。我真的应该使用 GeoDjango ,像这样调用几何图形:-

from boris.models import constituency
obj=constituency.objects.get(id=1)
geo_json=obj.shape.geojson
Run Code Online (Sandbox Code Playgroud)

但得到了 GDAL_ERROR 1: b'PROJ: proj_create_from_database: 找不到 proj.db'

我相信 GDAL 库配置不正确 - 我可以尝试修复这个问题

2/ 我现在打算使这个应用程序具有交互性,让用户选择选区、地区或根据他们的位置找到他们的选区,并返回尽可能多的有趣信息。

请随意评论、更正和添加任何有用的内容。

菲尔#anoobinneed