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.
Поисковые запросы расстояния
Доступность: PostGIS, MariaDB, MySQL, Oracle, SpatiaLite, PGRaster (Native)
Доступны следующие поисковые запросы расстояния:
distance_ltdistance_ltedistance_gtdistance_gte-
dwithin(кроме MariaDB и MySQL)
Примечание
Для измерения расстояний, а не выполнения запросов по ним, используйте функцию Distance.
В поисковые запросы расстояния передаётся кортеж, содержащий:
- Геометрический объект или растр, относительно которого выполняются вычисления; и
- Число или объект
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 |
|---|---|---|---|---|---|---|
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 (≥ 12.0.1) | 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 (≥ 23c) | X | X | X | ||
X | X | X | X | X | B | |
X | ||||||
X | X | X (≥ 12.0.1) | 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 (≥ 12.0.1) | X | X (LWGEOM/RTTOPO) | ||
X | |||||
X | X (≥ 23c) | X | X | X | |
X | X | X | X | X | |
X | |||||
X | X | X (≥ 12.0.1) | 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 | X |
Агрегатные функции
В следующей таблице приведена сводка агрегатных функций, специфичных для ГИС и доступных в каждой пространственной СУБД.
Агрегатная функция | PostGIS | Oracle | MariaDB | MySQL | SpatiaLite |
|---|---|---|---|---|---|
X | X (≥ 12.0.1) | 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/6.0/ref/contrib/gis/db-api/