Spec-Zone.ru › Django 5.2

API базы данных GeoDjango

Пространственные бэкенды

В настоящее время GeoDjango предоставляет следующие пространственные бэкенды для баз данных:

  • django.contrib.gis.db.backends.postgis
  • django.contrib.gis.db.backends.mysql
  • django.contrib.gis.db.backends.oracle
  • django.contrib.gis.db.backends.spatialite

Ограничения MySQL для пространственных данных

Django поддерживает пространственные функции, работающие с реальными геометриями, доступными в современных версиях MySQL. Однако пространственные функции не так богаты, как в других бэкендах, таких как PostGIS.

Поддержка растровых данных

RasterField в настоящее время реализована только для бэкенда PostGIS. Для растровых полей доступны пространственные запросы, но пространственные функции и агрегаты для растровых полей не реализованы.

Создание и сохранение моделей с геометрическими полями

Вот пример создания геометрического объекта (предполагается модель Zipcode):

>>> from zipcode.models import Zipcode
>>> z = Zipcode(code=77096, poly="POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))")
>>> z.save()

GEOSGeometry объекты также могут использоваться для сохранения геометрических моделей:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> poly = GEOSGeometry("POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))")
>>> z = Zipcode(code=77096, poly=poly)
>>> z.save()

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

>>> poly_3084 = GEOSGeometry(
...     "POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))", srid=3084
... )  # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal'
>>> z = Zipcode(code=78212, poly=poly_3084)
>>> z.save()
>>> from django.db import connection
>>> print(
...     connection.queries[-1]["sql"]
... )  # printing the last SQL statement executed (requires DEBUG=True)
INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326))

Таким образом, параметры геометрии могут передаваться с помощью объекта GEOSGeometry, WKT (Well Known Text [1]), HEXEWKB (специфично для PostGIS – геометрия WKB в шестнадцатеричном формате [2]) и GeoJSON (см. RFC 7946). По существу, если входной параметр не является объектом GEOSGeometry, поле геометрии попытается создать экземпляр GEOSGeometry из входных данных.

Дополнительную информацию о создании GEOSGeometry объектов см. в руководстве по GEOS.

Создание и сохранение моделей с растровыми полями

При создании растровых моделей растровое поле неявным образом преобразует входные данные в GDALRaster с использованием отложенной оценки. Следовательно, растровое поле будет принимать любой вход, который принимается конструктором GDALRaster.

Вот пример создания растрового объекта из растрового файла volcano.tif (предполагается модель Elevation):

>>> from elevation.models import Elevation
>>> dem = Elevation(name="Volcano", rast="/path/to/raster/volcano.tif")
>>> dem.save()

GDALRaster объекты также могут использоваться для сохранения растровых моделей:

>>> from django.contrib.gis.gdal import GDALRaster
>>> rast = GDALRaster(
...     {
...         "width": 10,
...         "height": 10,
...         "name": "Canyon",
...         "srid": 4326,
...         "scale": [0.1, -0.1],
...         "bands": [{"data": range(100)}],
...     }
... )
>>> dem = Elevation(name="Canyon", rast=rast)
>>> dem.save()

Обратите внимание, что это эквивалентно:

>>> dem = Elevation.objects.create(
...     name="Canyon",
...     rast={
...         "width": 10,
...         "height": 10,
...         "name": "Canyon",
...         "srid": 4326,
...         "scale": [0.1, -0.1],
...         "bands": [{"data": range(100)}],
...     },
... )

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

Типы запросов GeoDjango могут использоваться с любым методом менеджера, например, filter(), exclude() и т. д. Однако уникальные для GeoDjango типы запросов доступны только для пространственных полей.

Фильтры по «обычным» полям (например, CharField) могут быть объединены с фильтрами по географическим полям. Географические запросы принимают ввод геометрий и растровых данных с обеих сторон, и типы входных данных могут свободно смешиваться.

Общая структура географических запросов описана ниже. Полная справка находится в справочнике по пространственным запросам.

Запросы по геометрии

Географические запросы с геометриями имеют следующий общий вид (предполагается модель Zipcode, используемая в API моделей GeoDjango):

>>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Zipcode.objects.exclude(...)

Например:

>>> qs = Zipcode.objects.filter(poly__contains=pnt)
>>> qs = Elevation.objects.filter(poly__contains=rst)

В этом случае, poly — это географическое поле, contains — тип пространственного запроса, pnt — параметр (который может быть объектом GEOSGeometry или строкой GeoJSON, WKT или HEXEWKB), а rst — объект GDALRaster.

Запросы по растровым данным

Синтаксис запросов по растровым данным аналогичен синтаксису для геометрий. Единственное отличие состоит в том, что можно указать индекс канала как дополнительный параметр. Если индекс канала не указан, используется первый канал по умолчанию (индекс 0). В этом случае синтаксис идентичен синтаксису запросов по геометрии.

Для указания индекса канала можно указать дополнительный параметр с обеих сторон запроса. Слева используется синтаксис с двойным подчеркиванием для передачи индекса канала. Справа можно указать кортеж из растра и индекса канала.

Это приводит к следующей общей форме запросов, связанных с растровыми данными (предполагается модель Elevation, используемая в API моделей GeoDjango):

>>> qs = Elevation.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Elevation.objects.filter(<field>__<band_index>__<lookup_type>=<parameter>)
>>> qs = Elevation.objects.filter(<field>__<lookup_type>=(<raster_input, <band_index>)

Например:

>>> qs = Elevation.objects.filter(rast__contains=geom)
>>> qs = Elevation.objects.filter(rast__contains=rst)
>>> qs = Elevation.objects.filter(rast__1__contains=geom)
>>> qs = Elevation.objects.filter(rast__contains=(rst, 1))
>>> qs = Elevation.objects.filter(rast__1__contains=(rst, 1))

В примере слева rast — это географическое растровое поле, а contains — тип пространственного запроса. Справа, geom — вход геометрии, а rst — объект GDALRaster. Индекс канала по умолчанию равен 0 в первых двух запросах и установлен на 1 в остальных.

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

Тип поддержки растровых данных для всех запросов указан в таблице совместимости. Запросы, включающие растровые данные, в настоящее время доступны только для бэкенда PostGIS.

Запросы по расстоянию

Введение

Вычисление расстояний с пространственными данными — непростая задача, поскольку Земля не плоская. Некоторые запросы по расстоянию с полями в географической системе координат могут потребовать иного выражения из-за ограничений PostGIS. Подробнее об этом см. раздел Выбор SRID в документации API моделей GeoDjango.

Запросы по расстоянию

Доступно для: PostGIS, MariaDB, MySQL, Oracle, SpatiaLite, PGRaster (Нативно)

Доступны следующие запросы по расстоянию:

  • distance_lt
  • distance_lte
  • distance_gt
  • distance_gte
  • dwithin (кроме MariaDB и MySQL)

Примечание

Для измерения, а не для запросов по расстояниям, используйте функцию Distance.

Запросы по расстоянию принимают кортеж параметров, состоящий из:

  1. Геометрии или растра, на основе которой производятся вычисления; и
  2. Числа или объекта Distance, содержащего расстояние.

Если используется объект Distance, он может быть выражен в любых единицах (SQL использует единицы, преобразованные в единицы поля); в противном случае числовые параметры предполагаются в единицах поля.

Примечание

В PostGIS, ST_Distance_Sphere не ограничивает типы геометрии, с которыми выполняются запросы по географическому расстоянию. [3] Однако эти запросы могут занимать много времени, так как расстояния по большому кругу необходимо вычислять на лету для каждой строки в запросе. Это происходит потому, что пространственный индекс для традиционных полей геометрии не может использоваться.

Для повышения производительности запросов по расстоянию на WGS84 рекомендуется использовать географические столбцы в вашей базе данных, так как они могут использовать свой пространственный индекс в запросах по расстоянию. Вы можете указать GeoDjango использовать географический столбец, установив geography=True в определении вашего поля.

Например, предположим, что у нас есть модель SouthTexasCity (из тестов расстояний GeoDjango) в проектированной системе координат, пригодной для городов южной Техаса:

from django.contrib.gis.db import models


class SouthTexasCity(models.Model):
    name = models.CharField(max_length=30)
    # A projected coordinate system (only valid for South Texas!)
    # is used, units are in meters.
    point = models.PointField(srid=32140)

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

>>> from django.contrib.gis.geos import GEOSGeometry
>>> from django.contrib.gis.measure import D  # ``D`` is a shortcut for ``Distance``
>>> from geoapp.models import SouthTexasCity
# Distances will be calculated from this point, which does not have to be projected.
>>> pnt = GEOSGeometry("POINT(-96.876369 29.905320)", srid=4326)
# If numeric parameter, units of field (meters in this case) are assumed.
>>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000))
# Find all Cities within 7 km, > 20 miles away, and > 100 chains away (an obscure unit)
>>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7)))
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20)))
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100)))

Запросы к растрам работают аналогичным образом, заменяя поле геометрии point полем растра, или объект pnt объектом растра, или оба. Для указания индекса полосы растра входного значения справа можно передать кортеж из 3 элементов в запрос, как показано ниже:

>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(rst, 2, D(km=7)))

Где для запроса будет использоваться полоса с индексом 2 (третья полоса) растра rst.

Таблицы совместимости

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

В следующей таблице приводится сводка доступных пространственных запросов для каждого серверного пространственного хранилища данных. Запросы PostGIS Raster (PGRaster) разделены на три категории, описанные в разделе подробное описание растровых запросов: собственная поддержка N, двусторонняя собственная поддержка B и поддержка преобразования геометрии C.

Тип запроса

PostGIS

Oracle

MariaDB

MySQL [4]

SpatiaLite

PGRaster

bbcontains

X

X

X

X

N

bboverlaps

X

X

X

X

N

contained

X

X

X

X

N

contains

X

X

X

X

X

B

contains_properly

X

B

coveredby

X

X

X

X

B

covers

X

X

X

X

B

crosses

X

X

X

X

C

disjoint

X

X

X

X

X

B

distance_gt

X

X

X

X

X

N

distance_gte

X

X

X

X

X

N

distance_lt

X

X

X

X

X

N

distance_lte

X

X

X

X

X

N

dwithin

X

X

X

B

equals

X

X

X

X

X

C

exact

X

X

X

X

X

B

intersects

X

X

X

X

X

B

isempty

X

isvalid

X

X

X

X

overlaps

X

X

X

X

X

B

relate

X

X

X

X

C

same_as

X

X

X

X

X

B

touches

X

X

X

X

X

B

within

X

X

X

X

X

B

left

X

C

right

X

C

overlaps_left

X

B

overlaps_right

X

B

overlaps_above

X

C

overlaps_below

X

C

strictly_above

X

C

strictly_below

X

C

Функции баз данных

В следующей таблице приведён обзор доступных функций баз данных, специфичных для географии, для каждого пространственного бэкэнда.

Функция

PostGIS

Oracle

MariaDB

MySQL

SpatiaLite

Area

X

X

X

X

X

AsGeoJSON

X

X

X

X

X

AsGML

X

X

X

AsKML

X

X

AsSVG

X

X

AsWKB

X

X

X

X

X

AsWKT

X

X

X

X

X

Azimuth

X

X (LWGEOM/RTTOPO)

BoundingCircle

X

X

X (≥ 5.1)

Centroid

X

X

X

X

X

ClosestPoint

X

X

Difference

X

X

X

X

X

Distance

X

X

X

X

X

Envelope

X

X

X

X

X

ForcePolygonCW

X

X

FromWKB

X

X

X

X

X

FromWKT

X

X

X

X

X

GeoHash

X

X

X (LWGEOM/RTTOPO)

GeometryDistance

X

Intersection

X

X

X

X

X

IsEmpty

X

IsValid

X

X

X

X

Length

X

X

X

X

X

LineLocatePoint

X

X

MakeValid

X

X (LWGEOM/RTTOPO)

MemSize

X

NumGeometries

X

X

X

X

X

NumPoints

X

X

X

X

X

Perimeter

X

X

X

PointOnSurface

X

X

X

X

Reverse

X

X

X

Scale

X

X

SnapToGrid

X

X

SymDifference

X

X

X

X

X

Transform

X

X

X

Translate

X

X

Union

X

X

X

X

X

Функции агрегирования

В следующей таблице представлен обзор доступных функций агрегирования, специфичных для ГИС, на каждом пространственном бэкенде. Обратите внимание, что MariaDB не поддерживает ни одну из этих агрегатных функций и поэтому исключена из таблицы.

Агрегат

PostGIS

Oracle

MySQL

SpatiaLite

Collect

X

X (≥ 8.0.24)

X

Extent

X

X

X

Extent3D

X

MakeLine

X

X

Union

X

X

X

Примечания

[1]

См. Open Geospatial Consortium, Inc., Спецификацию OpenGIS Simple Feature Specification For SQL, Документ 99-049 (5 мая 1999 г.), в гл. 3.2.5, стр. 3-11 (Текстовое представление геометрии SQL).

[2]

См. PostGIS EWKB, EWKT и канонические формы, документацию PostGIS в гл. 4.1.2.

[3]

См. документацию PostGIS по ST_DistanceSphere.

[4]

См. раздел Ограничения MySQL для пространственных данных для получения дополнительной информации.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.2/ref/contrib/gis/db-api/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API