• 3.2
  • 5.0
  • 6.1
  • Версия документации: 3.1

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

Before MySQL 5.6.1, spatial extensions only support bounding box operations (what MySQL calls minimum bounding rectangles, or MBR). Specifically, MySQL did not conform to the OGC standard. Django supports spatial functions operating on real geometries available in modern MySQL versions. However, the spatial functions are not as rich as other backends like PostGIS.

Changed in Django 3.0:

Support for spatial functions operating on real geometries was added.

Предупреждение

True spatial indexes (R-trees) are only supported with MyISAM tables on MySQL. [4] In other words, when using MySQL spatial extensions you have to choose between fast spatial lookups and the integrity of your data – MyISAM tables do not support transactions or foreign key constraints.

Поддержка растров

RasterField в настоящее время реализован только для серверной части PostGIS. Пространственный поиск доступен для растровых полей, но функции и агрегаты пространственной базы данных не реализованы для растровых полей.

Создание и сохранение моделей с геометрическими полями

Here is an example of how to create a geometry object (assuming the Zipcode model):

>>> from zipcode.models import Zipcode
>>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
>>> z.save()

GEOSGeometry objects may also be used to save geometric models:

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

Moreover, if the GEOSGeometry is in a different coordinate system (has a different SRID value) than that of the field, then it will be implicitly transformed into the SRID of the model’s field, using the spatial database’s transform procedure:

>>> 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.

Here is an example of how to create a raster object from a raster file volcano.tif (assuming the Elevation model):

>>> from elevation.models import Elevation
>>> dem = Elevation(name='Volcano', rast='/path/to/raster/volcano.tif')
>>> dem.save()

GDALRaster objects may also be used to save raster models:

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

Note that this equivalent to:

>>> 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) могут быть связаны с фильтрами для географических полей. Географический поиск принимает геометрические и растровые данные с обеих сторон, а типы входных данных можно свободно смешивать.

Общая структура географического поиска описана ниже. Полную ссылку можно найти в ссылке на пространственный поиск <spatial-lookups>.

Поиск по геометрии

Geographic queries with geometries take the following general form (assuming the Zipcode model used in the 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). В этом случае синтаксис идентичен синтаксису поиска по геометрии.

Чтобы указать индекс полосы, можно указать дополнительный параметр с обеих сторон поиска. С левой стороны синтаксис двойного подчеркивания используется для передачи индекса полосы. С правой стороны можно указать кортеж растра и индекса канала.

This results in the following general form for lookups involving rasters (assuming the Elevation model used in the 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» в остальных.

Хотя все пространственные запросы можно использовать с растровыми объектами с обеих сторон, не все базовые операторы изначально принимают растровые входные данные. В тех случаях, когда оператор ожидает ввода геометрии, растр автоматически преобразуется в геометрию. Важно помнить об этом при интерпретации результатов поиска.

Тип поддержки растра указан для всех поисков в таблице совместимости <spatial-lookup-compatibility>. Поиски с использованием растров в настоящее время доступны только для серверной части PostGIS.

Дистанционные запросы

Введение

Расчеты расстояний с использованием пространственных данных сложны, поскольку, к сожалению, Земля не плоская. Некоторые запросы расстояния с полями в географической системе координат, возможно, придется выражать по-другому из-за ограничений PostGIS. Дополнительную информацию см. в разделе Выбор SRID в документации API модели GeoDjango.

Дистанционные поиски

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

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

Примечание

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

Поиск по расстоянию принимает параметр кортежа, содержащий:

  1. Геометрия или растр для базовых вычислений; и

  2. Число или объект Distance, содержащий расстояние.

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

Примечание

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

Для гораздо большей производительности при выполнении запросов на расстояние WGS84 рассмотрите возможность использования столбцов geography <geography-type>` в вашей базе данных, поскольку они могут использовать свой пространственный индекс в запросах на расстояние. Вы можете указать GeoDjango использовать столбец «география», установив «geography=True» в определении поля.

Например, предположим, что у нас есть модель SouthTexasCity (из дистанционных тестов GeoDjango <tests/gis_tests/distapp/models.py>`) в проецируемой системе координат, действующей для городов южного Техаса:

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)

Then distance queries may be performed as follows:

>>> 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)))

Raster queries work the same way by replacing the geometry field point with a raster field, or the pnt object with a raster object, or both. To specify the band index of a raster input on the right hand side, a 3-tuple can be passed to the lookup as follows:

>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(rst, 2, D(km=7)))

Где для поиска будет использоваться канал с индексом 2 (третий канал) растра «первый».

Таблицы совместимости

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

В следующей таблице представлена ​​сводная информация о том, какие пространственные запросы доступны для каждой серверной части пространственной базы данных. Поиски растра PostGIS (PGRaster) разделены на три категории, описанные в подробных сведениях о поиске растра: встроенная поддержка N, двусторонняя встроенная поддержка B и поддержка преобразования геометрии C.

Тип поиска

ПостГИС

Оракул

МарияДБ

MySQL [5]

SpatiaLite

PGRaster

bbcontains

Х

Х

Х

Х

N

bboverlaps

Х

Х

Х

Х

N

содержится

Х

Х

Х

Х

N

содержит

Х

Х

Х

Х

Х

B

contains_properly

Х

B

coveredby

Х

Х

Х

B

обложки

Х

Х

Х

B

кресты

Х

Х

Х

Х

С

непересекающиеся

Х

Х

Х

Х

Х

B

distance_gt

Х

Х

Х

Х

Х

N

distance_gte

Х

Х

Х

Х

Х

N

distance_lt

Х

Х

Х

Х

Х

N

distance_lte

Х

Х

Х

Х

Х

N

dwithin

Х

Х

Х

B

равно

Х

Х

Х

Х

Х

С

точно

Х

Х

Х

Х

Х

B

пересекается

Х

Х

Х

Х

Х

B

действительно

Х

Х

X (≥ 5.7.5)

X (LWGEOM)

перекрывается

Х

Х

Х

Х

Х

B

связать

Х

Х

Х

Х

С

same_as

Х

Х

Х

Х

Х

B

касается

Х

Х

Х

Х

Х

B

внутри

Х

Х

Х

Х

Х

B

слева

Х

С

верно

Х

С

overlaps_left

Х

B

overlaps_right

Х

B

overlaps_above

Х

С

overlaps_below

Х

С

строго_выше

Х

С

строго_ниже

Х

С

Функции базы данных

В следующей таблице представлена ​​сводная информация о том, какие географические функции базы данных доступны на каждом пространственном сервере.

Функция

ПостГИС

Оракул

МарияДБ

MySQL

SpatiaLite

Площадь

Х

Х

Х

Х

Х

AsGeoJSON

Х

Х

X (≥ 10.2.4)

X (≥ 5.7.5)

Х

AsGML

Х

Х

Х

AsKML

Х

Х

AsSVG

Х

Х

AsWKB

Х

Х

Х

Х

Х

AsWKT

Х

Х

Х

Х

Х

Азимут

Х

X (LWGEOM)

BoundingCircle

Х

Х

Центроид

Х

Х

Х

Х

Х

Разница

Х

Х

Х

Х

Х

Расстояние

Х

Х

Х

Х

Х

Конверт

Х

Х

Х

Х

Х

ForcePolygonCW

Х

Х

GeoHash

Х

X (≥ 5.7.5)

X (LWGEOM)

Пересечение

Х

Х

Х

Х

Х

Действителен

Х

Х

X (≥ 5.7.5)

X (LWGEOM)

Длина

Х

Х

Х

Х

Х

LineLocatePoint

Х

Х

MakeValid

Х

X (LWGEOM)

MemSize

Х

NumGeometries

Х

Х

Х

Х

Х

NumPoints

Х

Х

Х

Х

Х

Периметр

Х

Х

Х

PointOnSurface

Х

Х

Х

Х

Реверс

Х

Х

Х

Масштаб

Х

Х

SnapToGrid

Х

Х

SymDifference

Х

Х

Х

Х

Х

Трансформировать

Х

Х

Х

Перевести

Х

Х

Союз

Х

Х

Х

Х

Х

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

The following table provides a summary of what GIS-specific aggregate functions are available on each spatial backend. Please note that MySQL does not support any of these aggregates, and is thus excluded from the table.

Совокупный

ПостГИС

Оракул

SpatiaLite

Собрать

Х

Х

Пространство

Х

Х

Х

Extent3D

Х

MakeLine

Х

Х

Союз

Х

Х

Х

Сноски

Back to Top