GeoDjango databas API¶
Spatiala backends¶
GeoDjango tillhandahåller för närvarande följande rumsliga databasbackends:
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 Spatiala begränsningar¶
Django stöder rumsliga funktioner som arbetar med verkliga geometrier som finns tillgängliga i moderna MySQL-versioner. De rumsliga funktionerna är dock inte lika rika som andra backends som PostGIS.
Stöd för raster¶
RasterField
är för närvarande endast implementerat för PostGIS-backend. Rumsliga uppslagningar är tillgängliga för rasterfält, men rumsliga databasfunktioner och aggregat är inte implementerade för rasterfält.
Skapa och spara modeller med geometriska fält¶
Här följer ett exempel på hur man skapar ett geometriobjekt (med utgångspunkt från modellen 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
-objekt kan också användas för att spara geometriska modeller:
>>> 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()
Om GEOSGeometry
dessutom befinner sig i ett annat koordinatsystem (har ett annat SRID-värde) än fältets, kommer det implicit att transformeras till SRID för modellens fält med hjälp av den rumsliga databasens transform-procedur:
>>> 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))
Geometriparametrar kan således skickas in med hjälp av objektet GEOSGeometry
, WKT (Well Known Text [1]), HEXEWKB (PostGIS-specifikt - en WKB-geometri i hexadecimal [2]) och GeoJSON (se RFC 7946). Om indata inte är ett GEOSGeometry
-objekt kommer geometrifältet att försöka skapa en GEOSGeometry
-instans från indata.
För mer information om att skapa GEOSGeometry
-objekt, se GEOS tutorial.
Skapa och spara modeller med Raster Fields¶
När rastermodeller skapas kommer rasterfältet implicit att konvertera indata till en GDALRaster
med hjälp av lazy-evaluation. Rasterfältet kommer därför att acceptera all indata som accepteras av GDALRaster
-konstruktören.
Här följer ett exempel på hur man skapar ett rasterobjekt från en rasterfil volcano.tif
(med modellen Elevation
):
>>> from elevation.models import Elevation
>>> dem = Elevation(name="Volcano", rast="/path/to/raster/volcano.tif")
>>> dem.save()
GDALRaster
-objekt kan också användas för att spara rastermodeller:
>>> 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()
Observera att detta är likvärdigt med:
>>> dem = Elevation.objects.create(
... name="Canyon",
... rast={
... "width": 10,
... "height": 10,
... "name": "Canyon",
... "srid": 4326,
... "scale": [0.1, -0.1],
... "bands": [{"data": range(100)}],
... },
... )
Rumsliga uppslagningar¶
GeoDjangos lookup-typer kan användas med alla managermetoder som filter()
, exclude()
, etc. De uppslagstyper som är unika för GeoDjango är dock endast tillgängliga på rumsliga fält.
Filter på ”normala” fält (t.ex. CharField
) kan kedjas med filter på geografiska fält. Geografiska uppslagningar accepterar geometri- och rasterinmatning på båda sidor och inmatningstyper kan blandas fritt.
Den allmänna strukturen för geografiska uppslagsord beskrivs nedan. En fullständig referens finns i :ref:spatial lookup reference<spatial-lookups>
.
Geometriuppslagningar¶
Geografiska frågor med geometrier har följande allmänna form (med antagande av modellen Zipcode
som används i GeoDjango modell-API):
>>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Zipcode.objects.exclude(...)
Till exempel:
>>> qs = Zipcode.objects.filter(poly__contains=pnt)
>>> qs = Elevation.objects.filter(poly__contains=rst)
I det här fallet är poly
det geografiska fältet, contains <gis-contains>`
är den rumsliga lookup-typen, pnt
är parametern (som kan vara ett GEOSGeometry
-objekt eller en sträng av GeoJSON , WKT eller HEXEWKB) och rst
är ett GDALRaster
-objekt.
Rasteruppslagningar¶
Syntaxen för rasteruppslagning liknar syntaxen för geometrier. Den enda skillnaden är att ett bandindex kan anges som ytterligare indata. Om inget bandindex anges används det första bandet som standard (index 0
). I så fall är syntaxen identisk med syntaxen för geometriuppslagningar.
För att ange bandindexet kan en ytterligare parameter anges på båda sidor av uppslagningen. På vänster sida används syntaxen med dubbla understreck för att skicka ett bandindex. På den högra sidan kan en tupel av raster- och bandindex specificeras.
Detta resulterar i följande allmänna form för uppslagningar som involverar raster (förutsatt att modellen Elevation
används i GeoDjango modell-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>)
Till exempel:
>>> 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))
Till vänster i exemplet är rast
det geografiska rasterfältet och :lookup:contains <gis-contains>
är den rumsliga lookup-typen. På höger sida är geom
en geometriingång och rst
är ett GDALRaster
-objekt. Bandindexet är som standard 0
i de två första frågorna och är inställt på 1
i de andra.
Alla spatiala uppslag kan användas med rasterobjekt på båda sidor, men det är inte alla underliggande operatörer som accepterar rasterinmatning. I de fall där operatören förväntar sig geometriinmatning konverteras rastret automatiskt till en geometri. Det är viktigt att ha detta i åtanke när man tolkar uppslagsresultaten.
Typen av rasterstöd listas för alla uppslagningar i kompatibilitetstabell. Uppslagningar som involverar raster är för närvarande endast tillgängliga för PostGIS-backend.
Frågor om avstånd¶
Introduktion¶
Avståndsberäkningar med rumsliga data är knepiga eftersom jorden tyvärr inte är platt. Vissa avståndsfrågor med fält i ett geografiskt koordinatsystem kan behöva uttryckas annorlunda på grund av begränsningar i PostGIS. Se avsnittet Välja en SRID i dokumentationen GeoDjango modell-API för mer information.
Uppslagning av avstånd¶
Tillgänglighet: PostGIS, MariaDB, MySQL, Oracle, SpatiaLite, PGRaster (inbyggd)
Följande avståndsuppslagningar är tillgängliga:
avstånd_lt
avstånd_lte
avstånd_gt
avstånd_gte
dwithin
(utom MariaDB och MySQL)
Observera
För mätning, snarare än förfrågningar om avstånd, använd funktionen Distance
.
Distansuppslagningar tar en tuple-parameter som består av:
En geometri eller ett raster att basera beräkningarna på; och
Ett tal eller
Distance
-objekt som innehåller avståndet.
Om ett Distance
-objekt används kan det uttryckas i valfri enhet (den SQL som genereras kommer att använda enheter som konverterats till fältets enheter); annars antas numeriska parametrar vara i fältets enheter.
Observera
I PostGIS begränsar ST_Distance_Sphere
inte de geometrityper som geografiska avståndsfrågor utförs med. [3] Dessa frågor kan dock ta lång tid, eftersom storcirkelavstånd måste beräknas i farten för varje rad i frågan. Detta beror på att det spatiala indexet på traditionella geometriska fält inte kan användas.
För mycket bättre prestanda på WGS84-avståndsfrågor, överväg att använda :ref:geografikolumner <geography-type>
i din databas istället eftersom de kan använda sitt rumsliga index i avståndsfrågor. Du kan tala om för GeoDjango att använda en geografikolumn genom att ställa in geography=True
i din fältdefinition.
Låt oss till exempel säga att vi har en SouthTexasCity
-modell (från GeoDjango distance tests ) på ett projicerat koordinatsystem som gäller för städer i södra Texas:
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)
Då kan avståndsfrågor utföras på följande sätt:
>>> 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)))
Rasterfrågor fungerar på samma sätt genom att geometrifältet point
ersätts med ett rasterfält, eller pnt
-objektet med ett rasterobjekt, eller båda. För att specificera bandindex för en rasterinmatning på höger sida kan en 3-tupel skickas till lookupen enligt följande:
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(rst, 2, D(km=7)))
Där bandet med index 2 (det tredje bandet) i rastret rst
skulle användas för uppslagningen.
Kompatibilitetstabeller¶
Rumsliga uppslagningar¶
I följande tabell finns en sammanfattning av vilka rumsliga uppslagningar som är tillgängliga för varje rumslig databasbackend. PostGIS Raster (PGRaster)-uppslagningarna är indelade i de tre kategorier som beskrivs i :ref:raster lookup details <spatial-lookup-raster>
: inbyggt stöd N
, bilateralt inbyggt stöd B
och stöd för geometrikonvertering C
.
Typ av uppslag |
PostGIS |
Oracle |
MariaDB |
MySQL [4] |
SpatiaLite |
PGRaster |
---|---|---|---|---|---|---|
|
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
N |
||
|
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
B |
|
|
X |
B |
||||
|
X |
X |
X |
X |
B |
|
|
X |
X |
X |
X |
B |
|
|
X |
X |
X |
X |
C |
|
X |
X |
X |
X |
X |
B |
|
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
X |
X |
X |
B |
|||
|
X |
X |
X |
X |
X |
C |
|
X |
X |
X |
X |
X |
B |
X |
X |
X |
X |
X |
B |
|
X |
||||||
X |
X |
X |
X |
|||
|
X |
X |
X |
X |
X |
B |
|
X |
X |
X |
X |
C |
|
|
X |
X |
X |
X |
X |
B |
X |
X |
X |
X |
X |
B |
|
|
X |
X |
X |
X |
X |
B |
|
X |
C |
||||
|
X |
C |
||||
X |
B |
|||||
X |
B |
|||||
X |
C |
|||||
X |
C |
|||||
|
X |
C |
||||
|
X |
C |
Databasfunktioner¶
I följande tabell finns en sammanfattning av vilka geografiskt specifika databasfunktioner som finns tillgängliga i varje rumslig backend.
Funktion |
PostGIS |
Oracle |
MariaDB |
MySQL |
SpatiaLite |
---|---|---|---|---|---|
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X |
|||
X |
X |
||||
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X (LWGEOM/RTTOPO) |
||||
X |
X |
X (≥ 5.1) |
|||
X |
X |
X |
X |
X |
|
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X (LWGEOM/RTTOPO) |
|||
X |
|||||
X |
X |
X |
X |
X |
|
X |
|||||
X |
X |
X |
X |
||
X |
X |
X |
X |
X |
|
X |
X |
||||
X |
X (LWGEOM/RTTOPO) |
||||
X |
|||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X |
|||
X |
X |
X |
X |
||
X |
X |
X |
|||
X |
X |
||||
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
|||
X |
X |
||||
X |
X |
X |
X |
X |
Aggregerade funktioner¶
I följande tabell finns en sammanfattning av vilka GIS-specifika aggregeringsfunktioner som finns tillgängliga på varje spatial backend. Observera att MariaDB inte stöder några av dessa aggregat och därför inte ingår i tabellen.
Sammanslagna |
PostGIS |
Oracle |
MySQL |
SpatiaLite |
---|---|---|---|---|
X |
X (≥ 8.0.24) |
X |
||
X |
X |
X |
||
X |
||||
X |
X |
|||
X |
X |
X |
Fotnoter