# Django 6.0.7 documentation

# 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 的空间限制

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 几何图形[#fnewkb]_）和 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()

Note that this is 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's lookup types may be used with any manager method like `filter()`, `exclude()`, etc. However, the lookup types unique to GeoDjango are only available on spatial fields.

Filters on 'normal' fields (e.g. `CharField`) may be chained with those on geographic fields. Geographic lookups accept geometry and raster input on both sides, and input types can be mixed freely in most cases. However, unlike assignments to model fields, with lookups, types such as `str`, `pathlib.Path`, and `dict` must be wrapped by `GDALRaster` to signify that the potential for file writing or network fetching is acceptable. For the rationale, see raster security considerations.

地理查找的一般结构如下所述。完整的参考信息可以在 空间查找参考 中找到。

Changed in Django 5.2.17:

In earlier versions, spatial lookups accepted `str` and `dict` types for new rasters, allowing file writes and network fetches.

### 空间查找

Geographic queries with geometries take the following general form (assuming the `Zipcode` model used in the 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`）。在这种情况下，语法与几何查找的语法相同。

要指定带索引，可以在查找的两侧指定附加参数。在左侧，使用双下划线语法传递带索引。在右侧，可以指定栅格和带索引的元组。

This results in the following general form for lookups involving rasters (assuming the `Elevation` model used in the 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 后端。

## 距离查询

### 介绍

Distance calculations with spatial data is tricky because, unfortunately, the Earth is not flat. Some distance queries with fields in a geographic coordinate system may have to be expressed differently because of limitations in PostGIS. Please see the 选择一个 SRID section for more details.

### 距离查找

可用性 ：PostGIS, MariaDB, MySQL, Oracle, SpatiaLite, PGRaster (Native)

以下是可用的距离查找：

- `distance_lt`

- `distance_lte`

- `distance_gt`

- `distance_gte`

- `dwithin` （除了 MariaDB 和 MySQL）

Note

对于 测量，而不是查询距离，使用 `Distance` 函数。

距离查找需要一个元组参数，包括：

1. 用于计算的几何体或栅格；和

2. 一个数字或 `Distance` 对象，包含距离。

如果使用了 `Distance` 对象，它可以用任何单位表示（生成的 SQL 将使用转换为字段单位的单位）；否则，数字参数被认为是字段的单位。

Note

In PostGIS, `ST_Distance_Sphere` does not limit the geometry types geographic distance queries are performed with. [3] However, these queries may take a long time, as great-circle distances must be calculated on the fly for every row in the query. This is because the spatial index on traditional geometry fields cannot be used.

为了在 WGS84 距离查询中获得更好的性能，考虑在数据库中使用 地理列，因为它们能够在距离查询中使用它们的空间索引。您可以通过在字段定义中设置 `geography=True` 来告诉 GeoDjango 使用地理列。

例如，假设我们有一个 `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)))

将使用栅格 `rst` 的带索引为 2（第三个带）进行查找。

## 兼容性表

### 空间查找

以下表格提供了每个空间数据库后端可用的空间查找的摘要。PostGIS 栅格（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 (≥ 12.0.1) | X | X | B
`covers` | X | 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
`geom_type` | X | X (≥ 23c) | X | X | X |
`intersects` | X | X | X | X | X | B
`isempty` | X |  |  |  | X |
`isvalid` | X | X | X (≥ 12.0.1) | X | X |
`num_dimensions` | X |  |  |  | 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 | 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 |  |  | X (≥ 5.1)
`Centroid` | X | X | X | X | X
`ClosestPoint` | X |  |  |  | X
`Difference` | X | X | X | X | X
`Distance` | X | X | X | X | X
`Envelope` | X | X | X | X | X
`ForcePolygonCW` | X |  |  |  | X
`FromWKB` | X | X | X | X | X
`FromWKT` | X | X | X | X | X
`GeoHash` | X |  | X (≥ 12.0.1) | X | X (LWGEOM/RTTOPO)
`GeometryDistance` | X |  |  |  |
`GeometryType` | X | X (≥ 23c) | X | X | X
`Intersection` | X | X | X | X | X
`IsEmpty` | X |  |  |  | X
`IsValid` | X | X | X (≥ 12.0.1) | X | X
`Length` | X | X | X | X | X
`LineLocatePoint` | X |  |  |  | X
`MakeValid` | X |  |  |  | X (LWGEOM/RTTOPO)
`MemSize` | X |  |  |  |
`NumDimensions` | X |  |  |  | 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
`Rotate` | 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

### 聚合函数

The following table provides a summary of what GIS-specific aggregate functions are available on each spatial backend.

聚合 | PostGIS | Oracle | MariaDB | MySQL | SpatiaLite
--- | --- | --- | --- | --- | ---
`Collect` | X |  | X (≥ 12.0.1) | X (≥ 8.0.24) | 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（1999 年 5 月 5 日），第 3.2.5 章，第 3-11 页（几何图形的 SQL 文本表示）。

[2]

请参阅 PostGIS EWKB、EWKT 和规范形式，PostGIS 文档第 4.1.2 章。

[3]

请参阅 PostGIS 文档 中关于 `ST_DistanceSphere` 的部分。

[4]

详情请参考 MySQL 的空间限制 部分。