• 3.1
  • 3.2
  • 5.0
  • Версия документации: 6.1

Учебник по ГеоДжанго

Введение

GeoDjango — это дополнительный модуль для Django, который превращает его в географическую веб-инфраструктуру мирового класса. GeoDjango стремится максимально упростить создание географических веб-приложений, таких как службы определения местоположения. Его особенности включают в себя:

  • Поля модели Django для геометрии OGC и растровых данных.

  • Расширения ORM Django для запроса и управления пространственными данными.

  • Слабосвязанные высокоуровневые интерфейсы Python для геометрических и растровых операций ГИС, а также манипулирования данными в различных форматах.

  • Редактирование полей геометрии из админа.

Это руководство предполагает знакомство с Django; таким образом, если вы новичок в Django, прочитайте обычное руководство, чтобы сначала ознакомиться с Django.

Примечание

У GeoDjango есть дополнительные требования, помимо тех, что требует Django. Для получения более подробной информации обратитесь к документации по установке.

Это руководство поможет вам создать географическое веб-приложение для просмотра «границ мира». [1] Часть кода, используемого в этом руководстве, взята из проекта _ базовых приложений GeoDjango и/или вдохновлена ​​им. [2]

Примечание

Последовательно изучите разделы руководства, чтобы получить пошаговые инструкции.

Настройка

Создайте пространственную базу данных

Обычно никакой специальной настройки не требуется, поэтому вы можете создать базу данных, как и для любого другого проекта. Мы даем несколько советов для выбранных баз данных:

Создать новый проект

Используйте стандартный скрипт django-admin для создания проекта под названием geodjango:

$ django-admin startproject geodjango
...\> django-admin startproject geodjango

Это инициализирует новый проект. Теперь создайте приложение World Django в проекте geodjango:

$ cd geodjango
$ python manage.py startapp world
...\> cd geodjango
...\> py manage.py startapp world

Настройте settings.py

Настройки проекта geodjango хранятся в файле geodjango/settings.py. Отредактируйте настройки подключения к базе данных в соответствии с вашими настройками:

DATABASES = {
    "default": {
        "ENGINE": "django.contrib.gis.db.backends.postgis",
        "NAME": "geodjango",
        "USER": "geo",
    },
}

Кроме того, измените настройку INSTALLED_APPS, включив в нее django.contrib.admin, django.contrib.gis и world (ваше вновь созданное приложение):

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.gis",
    "world",
]

Географические данные

Мировые границы

Данные о мировых границах доступны в этом zip-файле. Создайте каталог data в приложении world, загрузите данные о границах мира и разархивируйте. На платформах GNU/Linux используйте следующие команды:

$ mkdir world/data
$ cd world/data
$ wget https://web.archive.org/web/20231220150759/https://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
$ unzip TM_WORLD_BORDERS-0.3.zip
$ cd ../..
...\> mkdir world\data
...\> cd world\data
...\> wget https://web.archive.org/web/20231220150759/https://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
...\> unzip TM_WORLD_BORDERS-0.3.zip
...\> cd ..\..

ZIP-файл границ мира содержит набор файлов данных, известных как ESRI Shapefile, один из самых популярных форматов геопространственных данных. В разархивированном виде набор данных о мировых границах включает файлы со следующими расширениями:

  • .shp: содержит векторные данные для геометрии границ мира.

  • .shx: файл пространственного индекса для геометрии, хранящейся в .shp.

  • .dbf: файл базы данных для хранения данных негеометрических атрибутов (например, целочисленных и символьных полей).

  • .prj: Содержит информацию о пространственной привязке для географических данных, хранящихся в шейп-файле.

Используйте ogrinfo для изучения пространственных данных.

Утилита GDAL ogrinfo позволяет проверять метаданные шейп-файлов или других источников векторных данных:

$ ogrinfo world/data/TM_WORLD_BORDERS-0.3.shp
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
      using driver `ESRI Shapefile' successful.
1: TM_WORLD_BORDERS-0.3 (Polygon)
...\> ogrinfo world\data\TM_WORLD_BORDERS-0.3.shp
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
      using driver `ESRI Shapefile' successful.
1: TM_WORLD_BORDERS-0.3 (Polygon)

ogrinfo сообщает нам, что шейп-файл имеет один слой и что этот слой содержит данные полигонов. Чтобы узнать больше, мы укажем имя слоя и воспользуемся опцией -so, чтобы получить только важную сводную информацию:

$ ogrinfo -so world/data/TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
      using driver `ESRI Shapefile' successful.

Layer name: TM_WORLD_BORDERS-0.3
Metadata:
  DBF_DATE_LAST_UPDATE=2008-07-30
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["latitude",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["longitude",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FIPS: String (2.0)
ISO2: String (2.0)
ISO3: String (3.0)
UN: Integer (3.0)
NAME: String (50.0)
AREA: Integer (7.0)
POP2005: Integer64 (10.0)
REGION: Integer (3.0)
SUBREGION: Integer (3.0)
LON: Real (8.3)
LAT: Real (7.3)
...\> ogrinfo -so world\data\TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
      using driver `ESRI Shapefile' successful.

Layer name: TM_WORLD_BORDERS-0.3
Metadata:
  DBF_DATE_LAST_UPDATE=2008-07-30
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["latitude",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["longitude",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FIPS: String (2.0)
ISO2: String (2.0)
ISO3: String (3.0)
UN: Integer (3.0)
NAME: String (50.0)
AREA: Integer (7.0)
POP2005: Integer64 (10.0)
REGION: Integer (3.0)
SUBREGION: Integer (3.0)
LON: Real (8.3)
LAT: Real (7.3)

Эта подробная сводная информация сообщает нам количество объектов в слое (246), географические границы данных, систему пространственной привязки («SRS WKT»), а также информацию о типе для каждого поля атрибута. Например, FIPS: String (2.0) указывает, что символьное поле FIPS имеет максимальную длину 2. Аналогично, LON: Real (8.3) представляет собой поле с плавающей запятой, которое содержит максимум 8 цифр до трех десятичных знаков.

Географические модели

Определение географической модели

Теперь, когда вы изучили свой набор данных с помощью ogrinfo, создайте модель GeoDjango для представления этих данных:

from django.contrib.gis.db import models


class WorldBorder(models.Model):
    # Regular Django fields corresponding to the attributes in the
    # world borders shapefile.
    name = models.CharField(max_length=50)
    area = models.IntegerField()
    pop2005 = models.IntegerField("Population 2005")
    fips = models.CharField("FIPS Code", max_length=2, null=True)
    iso2 = models.CharField("2 Digit ISO", max_length=2)
    iso3 = models.CharField("3 Digit ISO", max_length=3)
    un = models.IntegerField("United Nations Code")
    region = models.IntegerField("Region Code")
    subregion = models.IntegerField("Sub-Region Code")
    lon = models.FloatField()
    lat = models.FloatField()

    # GeoDjango-specific: a geometry field (MultiPolygonField)
    mpoly = models.MultiPolygonField()

    # Returns the string representation of the model.
    def __str__(self):
        return self.name

Обратите внимание, что модуль models импортирован из django.contrib.gis.db.

Система пространственной привязки по умолчанию для геометрических полей — WGS84 (это означает, что SRID равен 4326) – другими словами, координаты поля указаны в парах долготы и широты в градусах. Чтобы использовать другую систему координат, установите SRID поля геометрии с помощью аргумента srid. Используйте целое число, представляющее код EPSG системы координат.

Запустите «миграцию»

После определения вашей модели вам необходимо синхронизировать ее с базой данных. Сначала создайте миграцию базы данных:

$ python manage.py makemigrations
Migrations for 'world':
  world/migrations/0001_initial.py:
    + Create model WorldBorder
...\> py manage.py makemigrations
Migrations for 'world':
  world/migrations/0001_initial.py:
    + Create model WorldBorder

Давайте посмотрим на SQL, который сгенерирует таблицу для модели WorldBorder:

$ python manage.py sqlmigrate world 0001
...\> py manage.py sqlmigrate world 0001

Эта команда должна выдать следующий результат:

BEGIN;
--
-- Create model WorldBorder
--
CREATE TABLE "world_worldborder" (
    "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    "name" varchar(50) NOT NULL,
    "area" integer NOT NULL,
    "pop2005" integer NOT NULL,
    "fips" varchar(2) NOT NULL,
    "iso2" varchar(2) NOT NULL,
    "iso3" varchar(3) NOT NULL,
    "un" integer NOT NULL,
    "region" integer NOT NULL,
    "subregion" integer NOT NULL,
    "lon" double precision NOT NULL,
    "lat" double precision NOT NULL
    "mpoly" geometry(MULTIPOLYGON,4326) NOT NULL
)
;
CREATE INDEX "world_worldborder_mpoly_id" ON "world_worldborder" USING GIST ("mpoly");
COMMIT;

Если это выглядит правильно, запустите migrate, чтобы создать эту таблицу в базе данных:

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, world
Running migrations:
  ...
  Applying world.0001_initial... OK
...\> py manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, world
Running migrations:
  ...
  Applying world.0001_initial... OK

Импорт пространственных данных

В этом разделе показано, как импортировать шейп-файл мировых границ в базу данных с помощью моделей GeoDjango, используя Утилита импорта данных LayerMapping.

Существует множество различных способов импорта данных в пространственную базу данных. Помимо инструментов, включенных в GeoDjango, вы также можете использовать следующие:

  • ogr2ogr: утилита командной строки, входящая в состав GDAL, которая может импортировать многие форматы векторных данных в базы данных PostGIS, MySQL и Oracle.

  • shp2pgsql: эта утилита, входящая в состав PostGIS, импортирует шейп-файлы ESRI в PostGIS.

ГДАЛ-интерфейс

Ранее вы использовали ogrinfo для проверки содержимого шейп-файла границ мира. GeoDjango также включает Pythonic-интерфейс для мощной библиотеки OGR GDAL, которая может работать со всеми источниками векторных данных, которые поддерживает OGR.

Сначала вызовите оболочку Django:

$ python manage.py shell
...\> py manage.py shell

Если вы загрузили данные Мировые границы ранее в этом руководстве, вы можете определить их путь, используя pathlib.Path Python:

>>> from pathlib import Path
>>> import world
>>> world_shp = Path(world.__file__).resolve().parent / "data" / "TM_WORLD_BORDERS-0.3.shp"

Теперь откройте шейп-файл границ мира, используя интерфейс GeoDjango DataSource:

>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource(world_shp)
>>> print(ds)
/ ... /geodjango/world/data/TM_WORLD_BORDERS-0.3.shp (ESRI Shapefile)

Объекты источника данных могут иметь разные слои геопространственных объектов; однако шейп-файлам разрешено иметь только один слой:

>>> print(len(ds))
1
>>> lyr = ds[0]
>>> print(lyr)
TM_WORLD_BORDERS-0.3

Вы можете увидеть тип геометрии слоя и количество объектов, которые он содержит:

>>> print(lyr.geom_type)
Polygon
>>> print(len(lyr))
246

Примечание

К сожалению, формат данных шейп-файла не обеспечивает большей специфичности в отношении типов геометрии. Этот шейп-файл, как и многие другие, на самом деле включает в себя геометрию MultiPolygon, а не Polygons. В моделях важно использовать более общий тип поля: GeoDjango MultiPolygonField принимает геометрию Polygon, но PolygonField не принимает геометрию типа MultiPolygon. Вот почему определенная выше модель WorldBorder использует MultiPolygonField.

Layer также может иметь связанную с ним систему пространственной привязки. Если это так, атрибут srs вернет объект SpatialReference:

>>> srs = lyr.srs
>>> print(srs)
GEOGCS["WGS 84",
DATUM["WGS_1984",
    SPHEROID["WGS 84",6378137,298.257223563,
        AUTHORITY["EPSG","7030"]],
    AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
    AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
    AUTHORITY["EPSG","9122"]],
AXIS["Latitude",NORTH],
AXIS["Longitude",EAST],
AUTHORITY["EPSG","4326"]]
>>> srs.proj  # PROJ representation
'+proj=longlat +datum=WGS84 +no_defs'

Этот шейп-файл находится в популярной системе пространственной привязки WGS84 — другими словами, в данных используются пары долготы и широты в градусах.

Кроме того, шейп-файлы также поддерживают поля атрибутов, которые могут содержать дополнительные данные. Вот поля на слое World Borders:

>>> print(lyr.fields)
['FIPS', 'ISO2', 'ISO3', 'UN', 'NAME', 'AREA', 'POP2005', 'REGION', 'SUBREGION', 'LON', 'LAT']

Следующий код позволит вам проверить типы OGR (например, целое число или строка), связанные с каждым из полей:

>>> [fld.__name__ for fld in lyr.field_types]
['OFTString', 'OFTString', 'OFTString', 'OFTInteger', 'OFTString', 'OFTInteger', 'OFTInteger64', 'OFTInteger', 'OFTInteger', 'OFTReal', 'OFTReal']

Вы можете перебирать каждый объект в слое и извлекать информацию как из геометрии объекта (доступ к которому осуществляется через атрибут geom), так и из полей атрибутов объекта (чьи значения доступны через метод get()):

>>> for feat in lyr:
...     print(feat.get("NAME"), feat.geom.num_points)
...
Guernsey 18
Jersey 26
South Georgia South Sandwich Islands 338
Taiwan 363

Объекты Layer могут быть нарезаны:

>>> lyr[0:2]
[<django.contrib.gis.gdal.feature.Feature object at 0x2f47690>, <django.contrib.gis.gdal.feature.Feature object at 0x2f47650>]

А отдельные функции можно получить по их идентификатору:

>>> feat = lyr[234]
>>> print(feat.get("NAME"))
San Marino

Граничную геометрию можно экспортировать в форматах WKT и GeoJSON:

>>> geom = feat.geom
>>> print(geom.wkt)
POLYGON ((12.415798 43.957954,12.450554 ...
>>> print(geom.json)
{ "type": "Polygon", "coordinates": [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...

Сопоставление слоев

Чтобы импортировать данные, используйте LayerMapping в скрипте Python. Создайте файл load.py внутри приложения world со следующим кодом:

from pathlib import Path
from django.contrib.gis.utils import LayerMapping
from .models import WorldBorder

world_mapping = {
    "fips": "FIPS",
    "iso2": "ISO2",
    "iso3": "ISO3",
    "un": "UN",
    "name": "NAME",
    "area": "AREA",
    "pop2005": "POP2005",
    "region": "REGION",
    "subregion": "SUBREGION",
    "lon": "LON",
    "lat": "LAT",
    "mpoly": "MULTIPOLYGON",
}

world_shp = Path(__file__).resolve().parent / "data" / "TM_WORLD_BORDERS-0.3.shp"


def run(verbose=True):
    lm = LayerMapping(WorldBorder, world_shp, world_mapping, transform=False)
    lm.save(strict=True, verbose=verbose)

Несколько замечаний о том, что происходит:

  • Каждый ключ в словаре world_mapping соответствует полю в модели WorldBorder. Значением является имя поля шейп-файла, из которого будут загружены данные.

  • Ключом mpoly для поля геометрии является MULTIPOLYGON, тип геометрии GeoDjango импортирует поле как. Даже простые полигоны в шейп-файле будут автоматически преобразованы в коллекции перед вставкой в ​​базу данных.

  • Путь к шейп-файлу не является абсолютным - другими словами, если вы переместите приложение world (с подкаталогом data) в другое место, скрипт все равно будет работать.

  • Для ключевого слова Transform установлено значение False, поскольку данные в шейп-файле не нужно преобразовывать — они уже находятся в WGS84 (SRID=4326).

После этого вызовите оболочку Django из каталога проекта geodjango:

$ python manage.py shell
...\> py manage.py shell

Затем импортируйте модуль load, вызовите процедуру run и наблюдайте, как LayerMapping выполняет работу:

>>> from world import load
>>> load.run()

Попробуйте ogrinspect

Теперь, когда вы увидели, как определять географические модели и импортировать данные с помощью Утилита импорта данных LayerMapping, можно дополнительно автоматизировать этот процесс с помощью команды управления ogrinspect. Команда ogrinspect анализирует источник векторных данных, поддерживаемый GDAL (например, шейп-файл), и автоматически генерирует определение модели и словарь LayerMapping.

Общее использование команды выглядит следующим образом:

$ python manage.py ogrinspect [options] <data_source> <model_name> [options]
...\> py manage.py ogrinspect [options] <data_source> <model_name> [options]

data_source — это путь к источнику данных, поддерживаемому GDAL, а model_name — имя, которое будет использоваться для модели. Параметры командной строки можно использовать для дальнейшего определения способа создания модели.

Например, следующая команда почти автоматически воспроизводит модель WorldBorder и словарь сопоставлений, созданный выше:

$ python manage.py ogrinspect world/data/TM_WORLD_BORDERS-0.3.shp WorldBorder \
    --srid=4326 --mapping --multi
...\> py manage.py ogrinspect world\data\TM_WORLD_BORDERS-0.3.shp WorldBorder \
    --srid=4326 --mapping --multi

Несколько замечаний по поводу параметров командной строки, приведенных выше:

  • Опция --srid=4326 устанавливает SRID для географического поля.

  • Опция --mapping указывает ogrinspect также генерировать словарь сопоставления для использования с LayerMapping.

  • Опция --multi указана так, что географическое поле представляет собой MultiPolygonField, а не просто PolygonField.

Команда выдает следующий вывод, который можно скопировать непосредственно в файл models.py приложения GeoDjango:

# This is an auto-generated Django model module created by ogrinspect.
from django.contrib.gis.db import models


class WorldBorder(models.Model):
    fips = models.CharField(max_length=2)
    iso2 = models.CharField(max_length=2)
    iso3 = models.CharField(max_length=3)
    un = models.IntegerField()
    name = models.CharField(max_length=50)
    area = models.IntegerField()
    pop2005 = models.IntegerField()
    region = models.IntegerField()
    subregion = models.IntegerField()
    lon = models.FloatField()
    lat = models.FloatField()
    geom = models.MultiPolygonField(srid=4326)


# Auto-generated `LayerMapping` dictionary for WorldBorder model
worldborders_mapping = {
    "fips": "FIPS",
    "iso2": "ISO2",
    "iso3": "ISO3",
    "un": "UN",
    "name": "NAME",
    "area": "AREA",
    "pop2005": "POP2005",
    "region": "REGION",
    "subregion": "SUBREGION",
    "lon": "LON",
    "lat": "LAT",
    "geom": "MULTIPOLYGON",
}

Пространственные запросы

Пространственные запросы

GeoDjango добавляет пространственный поиск в Django ORM. Например, вы можете найти страну в таблице WorldBorder, содержащей определенную точку. Сначала запустите оболочку управления:

$ python manage.py shell
...\> py manage.py shell

Теперь определите точку интереса [3]:

>>> pnt_wkt = "POINT(-95.3385 29.7245)"

Строка pnt_wkt представляет точку на -95,3385 градуса долготы и 29,7245 градуса широты. Геометрия имеет формат, известный как Well Known Text (WKT), стандарт, выпущенный Открытым геопространственным консорциумом (OGC). [4] Импортируйте модель WorldBorder и выполните поиск contains, используя pnt_wkt в качестве параметра:

>>> from world.models import WorldBorder
>>> WorldBorder.objects.filter(mpoly__contains=pnt_wkt)
<QuerySet [<WorldBorder: United States>]>

Здесь вы получили QuerySet только с одной моделью: границей Соединенных Штатов (именно то, что вы и ожидали).

Аналогичным образом вы также можете использовать объект геометрии GEOS. Здесь вы можете объединить пространственный поиск intersects с методом get, чтобы получить только экземпляр WorldBorder для Сан-Марино вместо набора запросов:

>>> from django.contrib.gis.geos import Point
>>> pnt = Point(12.4604, 43.9420)
>>> WorldBorder.objects.get(mpoly__intersects=pnt)
<WorldBorder: San Marino>

Поиски contains и intersects — это лишь подмножество доступных запросов; в документации API базы данных GeoDjango есть больше.

Автоматические пространственные преобразования

При выполнении пространственных запросов GeoDjango автоматически преобразует геометрию, если она находится в другой системе координат. В следующем примере координаты будут выражены в EPSG SRID 32140, системе координат, характерной только для южного Техаса, и в единицах метров, а не градусов:

>>> from django.contrib.gis.geos import GEOSGeometry, Point
>>> pnt = Point(954158.1, 4215137.1, srid=32140)

Обратите внимание, что pnt также может быть создан с помощью EWKT, «расширенной» формы WKT, включающей SRID:

>>> pnt = GEOSGeometry("SRID=32140;POINT(954158.1 4215137.1)")

ORM GeoDjango автоматически переносит значения геометрии в преобразование SQL, позволяя разработчику работать на более высоком уровне абстракции:

>>> qs = WorldBorder.objects.filter(mpoly__intersects=pnt)
>>> print(qs.query)  # Generating the SQL
SELECT "world_worldborder"."id", "world_worldborder"."name", "world_worldborder"."area",
"world_worldborder"."pop2005", "world_worldborder"."fips", "world_worldborder"."iso2",
"world_worldborder"."iso3", "world_worldborder"."un", "world_worldborder"."region",
"world_worldborder"."subregion", "world_worldborder"."lon", "world_worldborder"."lat",
"world_worldborder"."mpoly" FROM "world_worldborder"
WHERE ST_Intersects("world_worldborder"."mpoly", ST_Transform(%s, 4326))
>>> qs  # printing evaluates the queryset
<QuerySet [<WorldBorder: United States>]>

Необработанные запросы

При использовании raw запросов вы должны обернуть поля геометрии так, чтобы значение поля могло распознаваться GEOS:

>>> from django.db import connection
>>> # or if you're querying a non-default database:
>>> from django.db import connections
>>> connection = connections["your_gis_db_alias"]
>>> City.objects.raw(
...     "SELECT id, name, %s as point from myapp_city" % (connection.ops.select % "point")
... )

Вам следует использовать необработанные запросы только тогда, когда вы точно знаете, что делаете.

Ленивая геометрия

GeoDjango загружает геометрию в стандартизированном текстовом представлении. При первом доступе к геометрическому полю GeoDjango создает объект GEOSGeometry, предоставляющий мощные функциональные возможности, такие как свойства сериализации для популярных геопространственных форматов:

>>> sm = WorldBorder.objects.get(name="San Marino")
>>> sm.mpoly
<MultiPolygon object at 0x24c6798>
>>> sm.mpoly.wkt  # WKT
MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ...
>>> sm.mpoly.wkb  # WKB (as Python binary buffer)
<read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40>
>>> sm.mpoly.geojson  # GeoJSON
'{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...

Это включает в себя доступ ко всем расширенным геометрическим операциям, предоставляемым библиотекой GEOS:

>>> pnt = Point(12.4604, 43.9420)
>>> sm.mpoly.contains(pnt)
True
>>> pnt.contains(sm.mpoly)
False

Географические аннотации

GeoDjango также предлагает набор географических аннотаций для расчета расстояний и ряда других операций (пересечение, разность и т. д.). См. документацию Функции географических баз данных.

Размещение ваших данных на карте

Географический администратор

Приложение администратора Django поддерживает редактирование геометрических полей.

Основы

Администратор Django позволяет пользователям создавать и изменять геометрию на скользкой карте JavaScript (на базе OpenLayers`_).

Давайте приступим прямо к делу. Создайте файл admin.py внутри приложения world со следующим кодом:

from django.contrib.gis import admin
from .models import WorldBorder

admin.site.register(WorldBorder, admin.ModelAdmin)

Затем отредактируйте файл urls.py в папке приложения geodjango следующим образом:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("admin/", admin.site.urls),
]

Создайте пользователя-администратора:

$ python manage.py createsuperuser
...\> py manage.py createsuperuser

Затем запустите сервер разработки Django:

$ python manage.py runserver
...\> py manage.py runserver

Наконец, перейдите по адресу http://localhost:8000/admin/ и войдите в систему под именем только что созданного пользователя. Перейдите к любой из записей WorldBorder — границы можно редактировать, щелкнув многоугольник и перетащив вершины в нужное положение.

GISModelAdmin

С помощью GISModelAdmin GeoDjango использует слой OpenStreetMap в панели администратора. Это обеспечивает больше контекста (включая сведения об улицах и проездах), чем доступно с помощью ModelAdmin (который использует набор данных WMS Векторная карта уровня 0, размещенный в OSGeo).

Должны быть установлены файлы смещения датума PROJ (более подробную информацию см. в инструкции по установке PROJ <proj4>).

Если вы соответствуете этому требованию, используйте класс опции GISModelAdmin в файле admin.py:

admin.site.register(WorldBorder, admin.GISModelAdmin)

Сноски

Back to Top