---
title: "GeoDjango 模型 API"
version: 4.2
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/4.2/ref/contrib/gis/model-api/
canonical: https://djangodocs.dev/zh-hans/4.2/ref/contrib/gis/model-api/
---
# GeoDjango 模型 API

本文探讨了 GeoDjango 模型 API 的详细内容。在本节中，我们将使用以下地理模型作为示例，包括一个 [ZIP code](https://en.wikipedia.org/wiki/ZIP_code) 和一个 [Digital Elevation Model](https://en.wikipedia.org/wiki/Digital_elevation_model)。

```
from django.contrib.gis.db import models

class Zipcode(models.Model):
    code = models.CharField(max_length=5)
    poly = models.PolygonField()

class Elevation(models.Model):
    name = models.CharField(max_length=100)
    rast = models.RasterField()
```

## 空间字段类型

空间字段包括一系列几何字段类型和一个栅格字段类型。每种几何字段类型对应于 OpenGIS Simple Features 规范 [^1]。对于栅格数据，没有类似的标准。

### `GeometryField`

#### `class GeometryField`

几何字段的基类。

### `PointField`

#### `class PointField`

存储一个 [`Point`](/zh-hans/4.2/ref/contrib/gis/geos/#django.contrib.gis.geos.Point)。

### `LineStringField`

#### `class LineStringField`

存储一个 [`LineString`](/zh-hans/4.2/ref/contrib/gis/geos/#django.contrib.gis.geos.LineString)。

### `PolygonField`

#### `class PolygonField`

存储一个 [`Polygon`](/zh-hans/4.2/ref/contrib/gis/geos/#django.contrib.gis.geos.Polygon)。

### `MultiPointField`

#### `class MultiPointField`

存储一个 [`MultiPoint`](/zh-hans/4.2/ref/contrib/gis/geos/#django.contrib.gis.geos.MultiPoint)。

### `MultiLineStringField`

#### `class MultiLineStringField`

存储一个 [`MultiLineString`](/zh-hans/4.2/ref/contrib/gis/geos/#django.contrib.gis.geos.MultiLineString)。

### `MultiPolygonField`

#### `class MultiPolygonField`

存储一个 [`MultiPolygon`](/zh-hans/4.2/ref/contrib/gis/geos/#django.contrib.gis.geos.MultiPolygon)。

### `GeometryCollectionField`

#### `class GeometryCollectionField`

存储一个 [`GeometryCollection`](/zh-hans/4.2/ref/contrib/gis/geos/#django.contrib.gis.geos.GeometryCollection)。

### `RasterField`

#### `class RasterField`

存储一个 [`GDALRaster`](/zh-hans/4.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GDALRaster)。

`RasterField` 目前仅在 PostGIS 后端实现。

## 空间字段选项

除了 Django 模型字段可用的常规 常见模型字段选项 外，空间字段还有以下附加选项。所有这些选项都是可选的。

### `srid`

#### `BaseSpatialField.srid`

将几何字段的 SRID \[#fnogcsrid\]\_（空间参考系统标识）设置为给定值。默认值为 4326（也称为 [WGS84](https://en.wikipedia.org/wiki/WGS84)，单位为经度和纬度的度数）。

#### 选择一个 SRID

选择适合模型的合适 SRID 是开发人员需要仔细考虑的重要决策。SRID 是一个整数标识符，对应于用于解释空间数据库中的数据的投影系统。[^3] 投影系统为指定位置的坐标提供了上下文。虽然 [大地测量学](https://en.wikipedia.org/wiki/Geodesy) 的细节超出了本文档的范围，但一般问题是地球是球形的，而地球的表示（例如，纸质地图、网络地图）不是。

大多数人都熟悉使用纬度和经度来引用地球表面上的位置。然而，纬度和经度是角度，而不是距离。换句话说，虽然在平坦表面上两点之间的最短路径是一条直线，但在弯曲表面上（例如地球）上两点之间的最短路径是一个 [大圆](https://en.wikipedia.org/wiki/Great_circle) 的 *弧线*。[^4] 因此，需要额外的计算才能获得平面单位（例如，千米和英里）的距离。在以后的开发中，使用地理坐标系统可能会引入复杂性。例如，SpatiaLite 没有能力在使用地理坐标系统的情况下执行几何体之间的距离计算，例如构建一个查询来查找存储为 WGS84 的县边界周围5英里内的所有点。[^5]

地球表面的部分区域可以投影到二维或笛卡尔平面上。投影坐标系统对于区域特定的应用特别方便，例如，如果您知道您的数据库只涵盖了 [北堪萨斯](https://spatialreference.org/ref/epsg/2796/) 的几何体，那么您可以考虑使用针对该地区的投影系统。此外，投影坐标系统是用笛卡尔单位（例如米或英尺）定义的，使距离计算更加方便。

> **Note**
>
> 如果您希望在 PostGIS 中使用 WGS84 中的非点几何体执行任意距离查询，并且希望获得良好的性能，请启用 [`GeometryField.geography`](#django.contrib.gis.db.models.GeometryField.geography) 关键字，以便使用 [地理数据库类型](#geography-type)。

其他资源：

- [spatialreference.org](https://spatialreference.org/)：一个由 Django 驱动的空间参考系统数据库。
- [The State Plane Coordinate System](https://web.archive.org/web/20080302095452/http://welcome.warnercnr.colostate.edu/class_info/nr502/lg3/datums_coordinates/spcs.html)：一个涵盖美国使用的各种投影系统的网站。在美国遇到的大部分空间数据将采用这些坐标系统之一，而不是像 WGS84 这样的地理坐标系统。

### `spatial_index`

#### `BaseSpatialField.spatial_index`

默认为 `True`。为给定的几何字段创建一个空间索引。

> **Note**
>
> 这与 `db_index` 字段选项不同，因为空间索引是以与常规数据库索引不同的方式创建的。具体而言，空间索引通常是使用 R-Tree 的变种创建的，而常规数据库索引通常使用 B-Tree。

## 几何字段选项

几何字段还有其他可用的选项。以下所有选项都是可选的。

### `dim`

#### `GeometryField.dim`

此选项可用于自定义几何字段的坐标维度。默认情况下，它设置为 2，用于表示二维几何体。对于支持的空间后端，它可以设置为 3，以支持三维。

> **Note**
>
> 目前，对三维的支持仅限于 PostGIS 和 SpatiaLite 后端。

### `geography`

#### `GeometryField.geography`

如果设置为 `True`，此选项将创建一个数据库列，其类型为 geography，而不是 geometry。有关更多详细信息，请参阅下面的 [地理类型](#geography-type) 部分。

> **Note**
>
> 地理支持仅限于 PostGIS，并且会强制将 SRID 设置为 4326。

#### 地理类型

地理类型提供对使用地理坐标表示的空间要素的本地支持（例如，WGS84 经度/纬度）。[^6] 与几何类型使用的平面不同，地理类型使用其数据的球面表示。对地理列执行的距离和测量操作会自动采用大圆弧计算，并返回线性单位。换句话说，当对两个地理要素调用 `ST_Distance` 时，将返回以米为单位的值（与在 WGS84 中对几何列调用时返回的度数不同）。

由于地理计算涉及更多的数学运算，因此地理类型仅支持 PostGIS 空间查询的子集。实际上，这意味着除了 [距离查询](/zh-hans/4.2/ref/contrib/gis/geoquerysets/#distance-lookups) 之外，地理列仅支持以下其他 [空间查询](/zh-hans/4.2/ref/contrib/gis/geoquerysets/#spatial-lookups)：

- [`bboverlaps`](/zh-hans/4.2/ref/contrib/gis/geoquerysets/#std-fieldlookup-bboverlaps)
- [`coveredby`](/zh-hans/4.2/ref/contrib/gis/geoquerysets/#std-fieldlookup-coveredby)
- [`covers`](/zh-hans/4.2/ref/contrib/gis/geoquerysets/#std-fieldlookup-covers)
- [`intersects`](/zh-hans/4.2/ref/contrib/gis/geoquerysets/#std-fieldlookup-intersects)

如果您需要使用不支持地理类型作为输入的空间查询或聚合函数，您可以在查询中使用 [`Cast`](/zh-hans/4.2/ref/models/database-functions/#django.db.models.functions.Cast) 数据库函数将地理列转换为几何类型：

```
from django.contrib.gis.db.models import PointField
from django.db.models.functions import Cast

Zipcode.objects.annotate(geom=Cast("geography_field", PointField())).filter(
    geom__within=poly
)
```

有关更多信息，请查阅 PostGIS 文档中关于确定 [何时使用地理数据类型而不是几何数据类型](https://postgis.net/docs/using_postgis_dbmanagement.html#PostGIS_GeographyVSGeometry) 的有用部分。

**脚注**

[^1]: OpenGIS Consortium, Inc., [Simple Feature Specification For SQL](https://www.ogc.org/standards/sfs).

[^2]: *在第 2.3.8 章，第 39页 查看 id* （几何值和空间参考系统）。

[^3]: 通常情况下，SRID 整数对应于 EPSG（[欧洲石油调查集团](https://epsg.org/)）标识符。然而，它也可以与空间数据库的空间参考系统表中定义的自定义投影相关联。

[^4]: Terry A. Slocum, Robert B. McMaster, Fritz C. Kessler 和 Hugh H. Howard，《主题制图和地理可视化》（Prentice Hall，第二版），第 7.1.3 节。

[^5]: 这个限制不适用于 PostGIS。

[^6]: 请参考 [PostGIS Geography Type](https://postgis.net/docs/using_postgis_dbmanagement.html#PostGIS_Geography) 文档以获取更多详细信息。
