GeoDjango База данных API
Пространственные бэкенды
GeoDjango в настоящее время предоставляет следующие пространственные бэкенды базы данных:
django.contrib.gis.db.backends.postgisdjango.contrib.gis.db.backends.mysqldjango.contrib.gis.db.backends.oracledjango.contrib.gis.db.backends.spatialite
Ограничения MySQL пространственных расширений
До версии MySQL 5.6.1 пространственные расширения поддерживали только операции с огибающей (то, что MySQL называет минимальными прямоугольниками, или MBR). В частности, MySQL не соответствовал стандарту OGC. 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 в GeoDjango API моделей):
>>> 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 в GeoDjango API моделей):
>>> 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 в документации GeoDjango API моделей.
Запросы по расстоянию
Доступность: 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 рассмотрите использование географических столбцов в вашей базе данных, так как они могут использовать свой пространственный индекс в запросах по расстоянию. Вы можете указать 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 | B | ||
covers | 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 |
isvalid | X | X | X (≥ 5.7.5) | 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 (≥ 10.2.4) | X (≥ 5.7.5) | 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 | |||
Centroid | X | X | X | X | X |
Difference | X | X | X | X | X |
Distance | X | X | X | X | X |
Envelope | X | X | X | X | X |
ForcePolygonCW | X | X | |||
GeoHash | X | X (≥ 5.7.5) | X (LWGEOM/RTTOPO) | ||
Intersection | X | X | X | X | X |
IsValid | X | X | X (≥ 5.7.5) | 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 |
Функции агрегирования
В следующей таблице приведён сводный список доступных функций агрегирования, специфичных для ГИС, для каждого пространственного бэкенда. Обратите внимание, что MySQL не поддерживает ни одну из этих агрегаций и, следовательно, исключён из таблицы.
| Агрегация | PostGIS | Oracle | SpatiaLite |
|---|---|---|---|
Collect | X | 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/4.0/ref/contrib/gis/db-api/