Spec-Zone.ru › Django 4.1

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

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

В настоящее время 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 Spatial

До версии 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 (Хорошо Известный Текст [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_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 на растровый объект, или и то, и другое. Для указания индекса полосы растрового входного параметра справа можно передать в поиск тройку, как показано ниже:

>>> 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 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] См. Открытый геопространственный консорциум, Спецификация OpenGIS Simple Feature 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.1/ref/contrib/gis/db-api/

Spec-Zone.ru

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