API базы данных GeoDjango
Пространственные бэкенды
В настоящее время GeoDjango предоставляет следующие пространственные бэкенды для баз данных:
django.contrib.gis.db.backends.postgisdjango.contrib.gis.db.backends.mysqldjango.contrib.gis.db.backends.oracledjango.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_ltdistance_ltedistance_gtdistance_gte-
dwithin(кроме MariaDB и MySQL)
Примечание
Для измерения, а не для запросов по расстояниям, используйте функцию Distance.
Запросы по расстоянию принимают кортеж параметров, состоящий из:
- Геометрии или растра, на основе которой производятся вычисления; и
- Числа или объекта
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 |
|---|---|---|---|---|---|---|
X | X | X | X | N | ||
X | X | X | X | N | ||
X | X | X | X | N | ||
X | X | X | X | X | B | |
X | B | |||||
X | X | X | X | B | ||
X | X | X | X | B | ||
X | X | X | X | C | ||
X | X | X | X | X | B | |
X | X | X | X | X | N | |
X | X | X | X | X | N | |
X | X | X | X | X | N | |
X | X | X | X | X | N | |
X | X | X | B | |||
X | X | X | X | X | C | |
X | X | X | X | X | B | |
X | X | X | X | X | B | |
X | ||||||
X | X | X | X | |||
X | X | X | X | X | B | |
X | X | X | X | C | ||
X | X | X | X | X | B | |
X | X | X | X | X | B | |
X | X | X | X | X | B | |
X | C | |||||
X | C | |||||
X | B | |||||
X | B | |||||
X | C | |||||
X | C | |||||
X | C | |||||
X | C |
Функции баз данных
В следующей таблице приведён обзор доступных функций баз данных, специфичных для географии, для каждого пространственного бэкэнда.
Функция | PostGIS | Oracle | MariaDB | MySQL | SpatiaLite |
|---|---|---|---|---|---|
X | X | X | X | X | |
X | X | X | X | X | |
X | X | X | |||
X | X | ||||
X | X | ||||
X | X | X | X | X | |
X | X | X | X | X | |
X | X (LWGEOM/RTTOPO) | ||||
X | X | X (≥ 5.1) | |||
X | X | X | X | X | |
X | X | ||||
X | X | X | X | X | |
X | X | X | X | X | |
X | X | X | X | X | |
X | X | ||||
X | X | X | X | X | |
X | X | X | X | X | |
X | X | X (LWGEOM/RTTOPO) | |||
X | |||||
X | X | X | X | X | |
X | |||||
X | X | X | X | ||
X | X | X | X | X | |
X | X | ||||
X | X (LWGEOM/RTTOPO) | ||||
X | |||||
X | X | X | X | X | |
X | X | X | X | X | |
X | X | X | |||
X | X | X | X | ||
X | X | X | |||
X | X | ||||
X | X | ||||
X | X | X | X | X | |
X | X | X | |||
X | X | ||||
X | X | X | X | X |
Функции агрегирования
В следующей таблице представлен обзор доступных функций агрегирования, специфичных для ГИС, на каждом пространственном бэкенде. Обратите внимание, что MariaDB не поддерживает ни одну из этих агрегатных функций и поэтому исключена из таблицы.
Агрегат | PostGIS | Oracle | MySQL | SpatiaLite |
|---|---|---|---|---|
X | X (≥ 8.0.24) | X | ||
X | X | X | ||
X | ||||
X | X | |||
X | X | X |
Примечания
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.2/ref/contrib/gis/db-api/