Spec-Zone.ru › Django 6.0

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.

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

Доступность: PostGIS, MariaDB, MySQL, Oracle, SpatiaLite, PGRaster (Native)

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

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

Примечание

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

В поисковые запросы расстояния передаётся кортеж, содержащий:

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

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

Примечание

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

Для значительно более высокой производительности запросов расстояния в WGS84 рассмотрите возможность использования в базе данных столбцов типа geography, поскольку для запросов расстояния они могут использовать свой пространственный индекс. Чтобы GeoDjango использовал столбец типа geography, задайте 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 — растровым объектом или выполнить обе замены. Чтобы указать индекс канала растровых входных данных справа, можно передать поисковому запросу кортеж из трёх элементов, как показано ниже:

>>> 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 (≥ 12.0.1)

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

geom_type

X

X (≥ 23c)

X

X

X

intersects

X

X

X

X

X

B

isempty

X

isvalid

X

X

X (≥ 12.0.1)

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 (≥ 12.0.1)

X

X (LWGEOM/RTTOPO)

GeometryDistance

X

GeometryType

X

X (≥ 23c)

X

X

X

Intersection

X

X

X

X

X

IsEmpty

X

IsValid

X

X

X (≥ 12.0.1)

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

Rotate

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

Агрегатные функции

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

Агрегатная функция

PostGIS

Oracle

MariaDB

MySQL

SpatiaLite

Collect

X

X (≥ 12.0.1)

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 для SQL, документ 99-049 (5 мая 1999 г.), глава 3.2.5, стр. 3-11 (текстовое представление геометрии в SQL).

[2]

См. EWKB, EWKT и канонические формы PostGIS, документация 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/6.0/ref/contrib/gis/db-api/

Spec-Zone.ru

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