GeoDjango handledning¶
Introduktion¶
GeoDjango är en medföljande Contrib-modul för Django som förvandlar den till ett geografiskt webbramverk i världsklass. GeoDjango strävar efter att göra det så enkelt som möjligt att skapa geografiska webbapplikationer, t.ex. platsbaserade tjänster. Dess funktioner inkluderar:
Django-modellfält för OGC-geometrier och rasterdata.
Tillägg till Djangos ORM för frågor och manipulering av rumsliga data.
Löst kopplade Python-gränssnitt på hög nivå för GIS-geometri och rasteroperationer samt datahantering i olika format.
Redigering av geometriska fält från administratören.
Denna handledning förutsätter att du känner till Django; om du är helt ny på Django, läs därför igenom vanlig handledning för att bekanta dig med Django först.
Observera
GeoDjango har ytterligare krav utöver de som Django kräver – se installationsdokumentationen för mer information.
Denna handledning kommer att vägleda dig genom skapandet av en geografisk webbapplikation för visning av världsgränserna. [1] En del av koden som används i denna handledning är hämtad från och/eller inspirerad av projektet GeoDjango basic apps. [2]
Observera
Gå igenom handledningsavsnitten i tur och ordning för att få steg-för-steg-instruktioner.
Uppsättning¶
Skapa en rumslig databas¶
Vanligtvis krävs ingen speciell installation, så du kan skapa en databas som du skulle göra för vilket annat projekt som helst. Vi ger några tips för utvalda databaser:
Skapa ett nytt projekt¶
Använd standardskriptet django-admin för att skapa ett projekt som heter geodjango:
$ django-admin startproject geodjango
...\> django-admin startproject geodjango
Detta kommer att initiera ett nytt projekt. Nu skapar du en Django-applikation world inom geodjango-projektet:
$ cd geodjango
$ python manage.py startapp world
...\> cd geodjango
...\> py manage.py startapp world
Konfigurera settings.py¶
Projektinställningarna för geodjango lagras i filen geodjango/settings.py. Redigera databasanslutningsinställningarna så att de matchar din installation:
DATABASES = {
"default": {
"ENGINE": "django.contrib.gis.db.backends.postgis",
"NAME": "geodjango",
"USER": "geo",
},
}
Ändra dessutom inställningen INSTALLED_APPS så att den inkluderar django.contrib.admin, django.contrib.gis och world (din nyskapade applikation):
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.gis",
"world",
]
Geografiska data¶
Världsgränser¶
Data för landsgränser finns i denna zip-fil. Skapa en data-katalog i programmet world, hämta data för landsgränserna och packa upp dem. Använd följande kommandon på GNU/Linux-plattformar:
$ mkdir world/data
$ cd world/data
$ wget https://web.archive.org/web/20231220150759/https://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
$ unzip TM_WORLD_BORDERS-0.3.zip
$ cd ../..
...\> mkdir world\data
...\> cd world\data
...\> wget https://web.archive.org/web/20231220150759/https://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
...\> unzip TM_WORLD_BORDERS-0.3.zip
...\> cd ..\..
ZIP-filen med landsgränser innehåller en uppsättning datafiler som tillsammans kallas en ESRI Shapefile, ett av de mest populära geospatiala dataformaten. När den packats upp innehåller datamängden med landsgränser filer med följande filändelser:
.shp: Innehåller vektordata för världsgränsgeometrierna..shx: Rumslig indexfil för geometrier lagrade i.shp..dbf: Databasfil för icke-geometriska attributdata (t.ex. heltals- och teckenfält)..prj: Innehåller den rumsliga referensinformationen för de geografiska data som lagras i shapefilen.
Använd ogrinfo för att undersöka rumsliga data¶
GDAL:s verktyg ogrinfo gör det möjligt att undersöka metadata för shapefiler eller andra vektordatakällor:
$ ogrinfo world/data/TM_WORLD_BORDERS-0.3.shp
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
using driver `ESRI Shapefile' successful.
1: TM_WORLD_BORDERS-0.3 (Polygon)
...\> ogrinfo world\data\TM_WORLD_BORDERS-0.3.shp
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
using driver `ESRI Shapefile' successful.
1: TM_WORLD_BORDERS-0.3 (Polygon)
ogrinfo visar att shapefilen har ett lager och att detta lager innehåller polygondata. För att få mer information anger vi lagernamnet och använder alternativet -so för att endast få den viktiga sammanfattningsinformationen:
$ ogrinfo -so world/data/TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
using driver `ESRI Shapefile' successful.
Layer name: TM_WORLD_BORDERS-0.3
Metadata:
DBF_DATE_LAST_UPDATE=2008-07-30
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCRS["WGS 84",
DATUM["World Geodetic System 1984",
ELLIPSOID["WGS 84",6378137,298.257223563,
LENGTHUNIT["metre",1]]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
CS[ellipsoidal,2],
AXIS["latitude",north,
ORDER[1],
ANGLEUNIT["degree",0.0174532925199433]],
AXIS["longitude",east,
ORDER[2],
ANGLEUNIT["degree",0.0174532925199433]],
ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FIPS: String (2.0)
ISO2: String (2.0)
ISO3: String (3.0)
UN: Integer (3.0)
NAME: String (50.0)
AREA: Integer (7.0)
POP2005: Integer64 (10.0)
REGION: Integer (3.0)
SUBREGION: Integer (3.0)
LON: Real (8.3)
LAT: Real (7.3)
...\> ogrinfo -so world\data\TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
using driver `ESRI Shapefile' successful.
Layer name: TM_WORLD_BORDERS-0.3
Metadata:
DBF_DATE_LAST_UPDATE=2008-07-30
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCRS["WGS 84",
DATUM["World Geodetic System 1984",
ELLIPSOID["WGS 84",6378137,298.257223563,
LENGTHUNIT["metre",1]]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
CS[ellipsoidal,2],
AXIS["latitude",north,
ORDER[1],
ANGLEUNIT["degree",0.0174532925199433]],
AXIS["longitude",east,
ORDER[2],
ANGLEUNIT["degree",0.0174532925199433]],
ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FIPS: String (2.0)
ISO2: String (2.0)
ISO3: String (3.0)
UN: Integer (3.0)
NAME: String (50.0)
AREA: Integer (7.0)
POP2005: Integer64 (10.0)
REGION: Integer (3.0)
SUBREGION: Integer (3.0)
LON: Real (8.3)
LAT: Real (7.3)
Den detaljerade sammanfattningsinformationen visar antalet objekt i lagret (246), datans geografiska gränser, det spatiala referenssystemet (”SRS WKT”) samt typinformation för varje attributfält. Exempelvis anger FIPS: String (2.0) att teckenfältet FIPS har en maximal längd på 2. På samma sätt är LON: Real (8.3) ett flyttalsfält som rymmer högst 8 siffror med upp till tre decimaler.
Geografiska modeller¶
Definiera en geografisk modell¶
Nu när du har undersökt din dataset med hjälp av ogrinfo, skapa en GeoDjango modell för att representera dessa data:
from django.contrib.gis.db import models
class WorldBorder(models.Model):
# Regular Django fields corresponding to the attributes in the
# world borders shapefile.
name = models.CharField(max_length=50)
area = models.IntegerField()
pop2005 = models.IntegerField("Population 2005")
fips = models.CharField("FIPS Code", max_length=2, null=True)
iso2 = models.CharField("2 Digit ISO", max_length=2)
iso3 = models.CharField("3 Digit ISO", max_length=3)
un = models.IntegerField("United Nations Code")
region = models.IntegerField("Region Code")
subregion = models.IntegerField("Sub-Region Code")
lon = models.FloatField()
lat = models.FloatField()
# GeoDjango-specific: a geometry field (MultiPolygonField)
mpoly = models.MultiPolygonField()
# Returns the string representation of the model.
def __str__(self):
return self.name
Observera att modulen models importeras från django.contrib.gis.db.
Det spatiala referenssystemet som används som standard för geometrifält är WGS84 (vilket innebär att SRID är 4326) – med andra ord består fältkoordinaterna av longitud-/latitudpar i enheten grader. Om du vill använda ett annat koordinatsystem anger du geometrifältets SRID med argumentet srid. Använd ett heltal som representerar koordinatsystemets EPSG-kod.
Kör migrate¶
När du har definierat din modell måste du synkronisera den med databasen. Först skapar du en databasmigrering:
$ python manage.py makemigrations
Migrations for 'world':
world/migrations/0001_initial.py:
+ Create model WorldBorder
...\> py manage.py makemigrations
Migrations for 'world':
world/migrations/0001_initial.py:
+ Create model WorldBorder
Låt oss titta på den SQL som kommer att generera tabellen för modellen WorldBorder:
$ python manage.py sqlmigrate world 0001
...\> py manage.py sqlmigrate world 0001
Detta kommando bör ge följande resultat:
BEGIN;
--
-- Create model WorldBorder
--
CREATE TABLE "world_worldborder" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"name" varchar(50) NOT NULL,
"area" integer NOT NULL,
"pop2005" integer NOT NULL,
"fips" varchar(2) NOT NULL,
"iso2" varchar(2) NOT NULL,
"iso3" varchar(3) NOT NULL,
"un" integer NOT NULL,
"region" integer NOT NULL,
"subregion" integer NOT NULL,
"lon" double precision NOT NULL,
"lat" double precision NOT NULL
"mpoly" geometry(MULTIPOLYGON,4326) NOT NULL
)
;
CREATE INDEX "world_worldborder_mpoly_id" ON "world_worldborder" USING GIST ("mpoly");
COMMIT;
Om detta ser korrekt ut, kör migrate för att skapa denna tabell i databasen:
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, world
Running migrations:
...
Applying world.0001_initial... OK
...\> py manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, world
Running migrations:
...
Applying world.0001_initial... OK
Importera rumsliga data¶
Det här avsnittet visar hur shapefilen med landsgränser importeras till databasen via GeoDjango-modeller med LayerMapping verktyg för dataimport.
Det finns många olika sätt att importera data till en rumslig databas - förutom de verktyg som ingår i GeoDjango kan du också använda följande:
ogr2ogr: Ett kommandoradsverktyg som ingår i GDAL och som kan importera många vektordataformat till PostGIS-, MySQL- och Oracle-databaser.
shp2pgsql: Detta verktyg som ingår i PostGIS importerar ESRI shapefiler till PostGIS.
GDAL-gränssnitt¶
Tidigare användes ogrinfo för att undersöka innehållet i shapefilen med landsgränser. GeoDjango innehåller även ett Python-anpassat gränssnitt till GDAL:s kraftfulla OGR-bibliotek, som kan arbeta med alla vektordatakällor som OGR stöder.
Först anropar du Django-skalet:
$ python manage.py shell
...\> py manage.py shell
Om du hämtade data från Världsgränser tidigare i handledningen kan du bestämma dess sökväg med hjälp av Pythons pathlib.Path:
>>> from pathlib import Path
>>> import world
>>> world_shp = Path(world.__file__).resolve().parent / "data" / "TM_WORLD_BORDERS-0.3.shp"
Öppna nu shapefilen med världsgränser med hjälp av GeoDjangos DataSource-gränssnitt:
>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource(world_shp)
>>> print(ds)
/ ... /geodjango/world/data/TM_WORLD_BORDERS-0.3.shp (ESRI Shapefile)
Datakällobjekt kan ha olika lager av geospatiala funktioner, men shapefiler får bara ha ett lager:
>>> print(len(ds))
1
>>> lyr = ds[0]
>>> print(lyr)
TM_WORLD_BORDERS-0.3
Du kan se skiktets geometrityp och hur många funktioner det innehåller:
>>> print(lyr.geom_type)
Polygon
>>> print(len(lyr))
246
Observera
Tyvärr tillåter shapefilens dataformat inte större precision när det gäller geometrityper. Denna shapefil innehåller, liksom många andra, faktiskt MultiPolygon-geometrier, inte Polygoner. Det är viktigt att använda en mer generell fälttyp i modeller: ett GeoDjango-MultiPolygonField accepterar en Polygon-geometri, men ett PolygonField accepterar inte en geometri av typen MultiPolygon. Därför använder modellen WorldBorder ovan ett MultiPolygonField.
Layer kan också ha ett spatialt referenssystem kopplat till sig. Om så är fallet returnerar attributet srs ett SpatialReference-objekt:
>>> srs = lyr.srs
>>> print(srs)
GEOGCS["WGS 84",
DATUM["WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,
AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9122"]],
AXIS["Latitude",NORTH],
AXIS["Longitude",EAST],
AUTHORITY["EPSG","4326"]]
>>> srs.proj # PROJ representation
'+proj=longlat +datum=WGS84 +no_defs'
Denna shapefil är i det populära rumsliga referenssystemet WGS84 - med andra ord använder data par av longitud, latitud i enheter av grader.
Shapefiler stöder dessutom attributfält som kan innehålla ytterligare data. Här är fälten i lagret World Borders:
>>> print(lyr.fields)
['FIPS', 'ISO2', 'ISO3', 'UN', 'NAME', 'AREA', 'POP2005', 'REGION', 'SUBREGION', 'LON', 'LAT']
Med följande kod kan du undersöka de OGR-typer (t.ex. heltal eller sträng) som är associerade med vart och ett av fälten:
>>> [fld.__name__ for fld in lyr.field_types]
['OFTString', 'OFTString', 'OFTString', 'OFTInteger', 'OFTString', 'OFTInteger', 'OFTInteger64', 'OFTInteger', 'OFTInteger', 'OFTReal', 'OFTReal']
Du kan iterera över varje objekt i skiktet och extrahera information från både objektets geometri (som nås via attributet geom) och objektets attributfält (vars värden nås via metoden get()):
>>> for feat in lyr:
... print(feat.get("NAME"), feat.geom.num_points)
...
Guernsey 18
Jersey 26
South Georgia South Sandwich Islands 338
Taiwan 363
Layer-objekt kan skivas:
>>> lyr[0:2]
[<django.contrib.gis.gdal.feature.Feature object at 0x2f47690>, <django.contrib.gis.gdal.feature.Feature object at 0x2f47650>]
Och enskilda funktioner kan hämtas med hjälp av deras funktions-ID:
>>> feat = lyr[234]
>>> print(feat.get("NAME"))
San Marino
Gränsgeometrier kan exporteras som WKT och GeoJSON:
>>> geom = feat.geom
>>> print(geom.wkt)
POLYGON ((12.415798 43.957954,12.450554 ...
>>> print(geom.json)
{ "type": "Polygon", "coordinates": [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
LayerMapping¶
För att importera data använder du en LayerMapping i ett Python-skript. Skapa en fil som heter load.py i applikationen world med följande kod:
from pathlib import Path
from django.contrib.gis.utils import LayerMapping
from .models import WorldBorder
world_mapping = {
"fips": "FIPS",
"iso2": "ISO2",
"iso3": "ISO3",
"un": "UN",
"name": "NAME",
"area": "AREA",
"pop2005": "POP2005",
"region": "REGION",
"subregion": "SUBREGION",
"lon": "LON",
"lat": "LAT",
"mpoly": "MULTIPOLYGON",
}
world_shp = Path(__file__).resolve().parent / "data" / "TM_WORLD_BORDERS-0.3.shp"
def run(verbose=True):
lm = LayerMapping(WorldBorder, world_shp, world_mapping, transform=False)
lm.save(strict=True, verbose=verbose)
Några anteckningar om vad som händer:
Varje nyckel i ordboken
world_mappingmotsvarar ett fält i modellenWorldBorder. Värdet är namnet på shapefilens fält som data ska läsas in från.Nyckeln
mpolyför geometrifältet ärMULTIPOLYGON, den geometrityp som GeoDjango importerar fältet som. Även enkla polygoner i shapefilen konverteras automatiskt till samlingar innan de infogas i databasen.Sökvägen till shapefilen är inte absolut - med andra ord, om du flyttar programmet
world(med underkatalogendata) till en annan plats kommer skriptet fortfarande att fungera.Nyckelordet
transformär inställt påFalseeftersom data i shapefilen inte behöver konverteras - de finns redan i WGS84 (SRID=4326).
Därefter anropar du Django-skalet från projektkatalogen geodjango:
$ python manage.py shell
...\> py manage.py shell
Därefter importerar du modulen load, anropar rutinen run och ser LayerMapping göra jobbet:
>>> from world import load
>>> load.run()
Prova ogrinspect¶
Nu när du har sett hur geografiska modeller definieras och data importeras med LayerMapping verktyg för dataimport kan processen automatiseras ytterligare med administrationskommandot ogrinspect. Kommandot ogrinspect introspekterar en GDAL-stödd vektordatakälla (t.ex. en shapefil) och genererar automatiskt en modelldefinition och ordbok för LayerMapping.
Den allmänna användningen av kommandot går till på följande sätt:
$ python manage.py ogrinspect [options] <data_source> <model_name> [options]
...\> py manage.py ogrinspect [options] <data_source> <model_name> [options]
data_source är sökvägen till den GDAL-stödda datakällan och model_name är namnet som ska användas för modellen. Kommandoradsalternativ kan användas för att ytterligare definiera hur modellen genereras.
Exempelvis kan följande kommando nästan automatiskt reproducera modellen WorldBorder och mappningsordlistan som skapats ovan:
$ python manage.py ogrinspect world/data/TM_WORLD_BORDERS-0.3.shp WorldBorder \
--srid=4326 --mapping --multi
...\> py manage.py ogrinspect world\data\TM_WORLD_BORDERS-0.3.shp WorldBorder \
--srid=4326 --mapping --multi
Några kommentarer om de kommandoradsalternativ som anges ovan:
Alternativet
--srid=4326anger SRID för det geografiska fältet.Alternativet
--mappingsäger tillogrinspectatt även generera en mappningsordbok för användning medLayerMapping.Alternativet
--multianges så att det geografiska fältet är enMultiPolygonFieldistället för bara enPolygonField.
Kommandot ger följande resultat, som kan kopieras direkt till models.py i en GeoDjango-applikation:
# This is an auto-generated Django model module created by ogrinspect.
from django.contrib.gis.db import models
class WorldBorder(models.Model):
fips = models.CharField(max_length=2)
iso2 = models.CharField(max_length=2)
iso3 = models.CharField(max_length=3)
un = models.IntegerField()
name = models.CharField(max_length=50)
area = models.IntegerField()
pop2005 = models.IntegerField()
region = models.IntegerField()
subregion = models.IntegerField()
lon = models.FloatField()
lat = models.FloatField()
geom = models.MultiPolygonField(srid=4326)
# Auto-generated `LayerMapping` dictionary for WorldBorder model
worldborders_mapping = {
"fips": "FIPS",
"iso2": "ISO2",
"iso3": "ISO3",
"un": "UN",
"name": "NAME",
"area": "AREA",
"pop2005": "POP2005",
"region": "REGION",
"subregion": "SUBREGION",
"lon": "LON",
"lat": "LAT",
"geom": "MULTIPOLYGON",
}
Rumsliga frågor¶
Rumsliga uppslagningar¶
GeoDjango lägger till spatiala uppslag i Djangos ORM. Du kan till exempel hitta det land i tabellen WorldBorder som innehåller en viss punkt. Starta först administrationsskalet:
$ python manage.py shell
...\> py manage.py shell
Nu ska du definiera en intressepunkt [3]:
>>> pnt_wkt = "POINT(-95.3385 29.7245)"
Strängen pnt_wkt representerar punkten vid -95.3385 graders longitud och 29.7245 graders latitud. Geometrin är i formatet Well Known Text (WKT), en standard utfärdad av Open Geospatial Consortium (OGC). [4] Importera modellen WorldBorder och utför ett uppslag med contains där pnt_wkt används som parameter:
>>> from world.models import WorldBorder
>>> WorldBorder.objects.filter(mpoly__contains=pnt_wkt)
<QuerySet [<WorldBorder: United States>]>
Här hämtade du en QuerySet med endast en modellinstans: USA:s gräns (precis vad du skulle förvänta dig).
På samma sätt kan du även använda ett GEOS-geometriobjekt. Här kan du kombinera det spatiala uppslaget intersects med metoden get för att hämta endast WorldBorder-instansen för San Marino i stället för en frågeuppsättning:
>>> from django.contrib.gis.geos import Point
>>> pnt = Point(12.4604, 43.9420)
>>> WorldBorder.objects.get(mpoly__intersects=pnt)
<WorldBorder: San Marino>
Uppslagen contains och intersects är bara en delmängd av de tillgängliga frågorna – dokumentationen GeoDjango databas API innehåller mer.
Automatiska rumsliga omvandlingar¶
När spatiala frågor utförs transformerar GeoDjango automatiskt geometrier om de använder ett annat koordinatsystem. I följande exempel uttrycks koordinaterna i EPSG SRID 32140, ett koordinatsystem specifikt för södra Texas endast och i enheten meter, inte grader:
>>> from django.contrib.gis.geos import GEOSGeometry, Point
>>> pnt = Point(954158.1, 4215137.1, srid=32140)
Observera att pnt också kan konstrueras med EWKT, en ”utökad” form av WKT som inkluderar SRID:
>>> pnt = GEOSGeometry("SRID=32140;POINT(954158.1 4215137.1)")
GeoDjangos ORM slår automatiskt in geometrivärden i transformations-SQL, vilket gör att utvecklaren kan arbeta på en högre abstraktionsnivå:
>>> qs = WorldBorder.objects.filter(mpoly__intersects=pnt)
>>> print(qs.query) # Generating the SQL
SELECT "world_worldborder"."id", "world_worldborder"."name", "world_worldborder"."area",
"world_worldborder"."pop2005", "world_worldborder"."fips", "world_worldborder"."iso2",
"world_worldborder"."iso3", "world_worldborder"."un", "world_worldborder"."region",
"world_worldborder"."subregion", "world_worldborder"."lon", "world_worldborder"."lat",
"world_worldborder"."mpoly" FROM "world_worldborder"
WHERE ST_Intersects("world_worldborder"."mpoly", ST_Transform(%s, 4326))
>>> qs # printing evaluates the queryset
<QuerySet [<WorldBorder: United States>]>
Råa förfrågningar
När du använder raw queries måste du omsluta dina geometrifält så att fältvärdet kan identifieras av GEOS:
>>> from django.db import connection
>>> # or if you're querying a non-default database:
>>> from django.db import connections
>>> connection = connections["your_gis_db_alias"]
>>> City.objects.raw(
... "SELECT id, name, %s as point from myapp_city" % (connection.ops.select % "point")
... )
Du bör bara använda råa frågor när du vet exakt vad du gör.
Lata geometrier¶
GeoDjango läser in geometrier i en standardiserad textrepresentation. När geometrifältet används första gången skapar GeoDjango ett GEOSGeometry-objekt som exponerar kraftfull funktionalitet, som serialiseringsegenskaper för populära geospatiala format:
>>> sm = WorldBorder.objects.get(name="San Marino")
>>> sm.mpoly
<MultiPolygon object at 0x24c6798>
>>> sm.mpoly.wkt # WKT
MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ...
>>> sm.mpoly.wkb # WKB (as Python binary buffer)
<read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40>
>>> sm.mpoly.geojson # GeoJSON
'{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
Detta inkluderar tillgång till alla avancerade geometriska operationer som tillhandahålls av GEOS-biblioteket:
>>> pnt = Point(12.4604, 43.9420)
>>> sm.mpoly.contains(pnt)
True
>>> pnt.contains(sm.mpoly)
False
Geografiska anteckningar¶
GeoDjango erbjuder också en uppsättning geografiska annoteringar för att beräkna avstånd och flera andra operationer (skärning, differens osv.). Se dokumentationen Geografiska databasfunktioner.
Placera dina data på kartan¶
Geografisk administratör¶
Djangos admin-applikation stöder redigering av geometriska fält.
Grundläggande¶
Django-admin låter användare skapa och ändra geometrier på en JavaScript-karta (som drivs av OpenLayers).
Låt oss dyka rätt in. Skapa en fil som heter admin.py inuti applikationen world med följande kod:
from django.contrib.gis import admin
from .models import WorldBorder
admin.site.register(WorldBorder, admin.ModelAdmin)
Därefter redigerar du din urls.py i applikationsmappen geodjango enligt följande:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
]
Skapa en administratörsanvändare:
$ python manage.py createsuperuser
...\> py manage.py createsuperuser
Starta sedan upp Django-utvecklingsservern:
$ python manage.py runserver
...\> py manage.py runserver
Slutligen, bläddra till http://localhost:8000/admin/ och logga in med den användare du just skapat. Bläddra till någon av WorldBorder-posterna - gränserna kan redigeras genom att klicka på en polygon och dra hörnen till önskad position.
GISModelAdmin¶
Med GISModelAdmin använder GeoDjango ett OpenStreetMap-lager i admin. Detta ger mer sammanhang (inklusive detaljer om gator och genomfartsleder) än vad som är tillgängligt med ModelAdmin (som använder WMS-datasetet Vector Map Level 0 som finns hos OSGeo).
PROJ datumskiftesfiler måste installeras (se PROJ installationsinstruktioner för mer information).
Om du uppfyller detta krav kan du använda alternativklassen GISModelAdmin i filen admin.py:
admin.site.register(WorldBorder, admin.GISModelAdmin)
Fotnoter