Учебник по GeoDjango

Вступление

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

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

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

Примечание

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

Это руководство поможет вам создать географическое веб-приложение для просмотра world borders. [1] Часть кода, используемого в этом руководстве, взята из проекта GeoDjango basic apps и/или вдохновлена им. [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 file. Создайте каталог data в приложении world, загрузите данные о границах мира и распакуйте. На платформах GNU/Linux используйте следующие команды:

$ mkdir world/data
$ cd world/data
$ wget 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://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
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCS["GCS_WGS_1984",
    DATUM["WGS_1984",
        SPHEROID["WGS_1984",6378137.0,298.257223563]],
    PRIMEM["Greenwich",0.0],
    UNIT["Degree",0.0174532925199433]]
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: Integer (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
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCS["GCS_WGS_1984",
    DATUM["WGS_1984",
        SPHEROID["WGS_1984",6378137.0,298.257223563]],
    PRIMEM["Greenwich",0.0],
    UNIT["Degree",0.0174532925199433]]
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: Integer (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 системы координат.

Выполнить migrate

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

$ 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" bigserial NOT NULL PRIMARY KEY,
    "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.

Интерфейс GDAL

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

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

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

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

>>> 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 - другими словами, в данных используются пары долгота-широта в единицах градусов.

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

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

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

>>> [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

To import the data, use a LayerMapping in a Python script. Create a file called load.py inside the world application, with the following code:

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 geometry object. Здесь можно объединить пространственный поиск 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 queries необходимо обернуть поля геометрии так, чтобы значение поля могло быть распознано 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 также предлагает набор географических аннотаций для вычисления расстояний и некоторых других операций (пересечение, разность и т.д.). См. документацию Функции географической базы данных.

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

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

GeoDjango расширяет Django’s admin application поддержкой редактирования геометрических полей.

Основы

GeoDjango также дополняет админку Django, позволяя пользователям создавать и изменять геометрии на скользкой карте JavaScript (на основе OpenLayers).

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

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

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

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

from django.contrib.gis 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 - границы можно редактировать, щелкнув на многоугольнике и перетащив вершины в нужное положение.

OSMGeoAdmin

With the OSMGeoAdmin, GeoDjango uses an OpenStreetMap layer in the admin. This provides more context (including street and thoroughfare details) than available with the GeoModelAdmin (which uses the Vector Map Level 0 WMS dataset hosted at OSGeo).

Должны быть установлены файлы сдвига датировок PROJ (более подробную информацию см. в PROJ installation instructions).

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

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

Сноски

[1]Особая благодарность Бьорну Сандвику из thematicmapping.org за предоставление и поддержку этого набора данных.
[2]Базовые приложения GeoDjango были написаны Дейном Спрингмейером, Джошем Ливни и Кристофером Шмидтом.
[3]Эта точка является точкой University of Houston Law Center.
[4]Open Geospatial Consortium, Inc., OpenGIS Simple Feature Specification For SQL.
Вернуться на верх