---
title: "GeoDjango handledning"
version: 5.2
locale: sv
source: https://docs.djangoproject.com/sv/5.2/ref/contrib/gis/tutorial/
canonical: https://djangodocs.dev/sv/5.2/ref/contrib/gis/tutorial/
---
# 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](https://www.ogc.org/)-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](/sv/5.2/intro/tutorial01/) för att bekanta dig med Django först.

> **Note**
>
> GeoDjango har ytterligare krav utöver vad Django kräver - se [installationsdokumentation](/sv/5.2/ref/contrib/gis/install/) för mer information.

Denna handledning kommer att vägleda dig genom skapandet av en geografisk webbapplikation för visning av [världsgränserna](https://web.archive.org/web/20240123190237/https://thematicmapping.org/downloads/world_borders.php). [^1] En del av koden som används i denna handledning är hämtad från och/eller inspirerad av projektet [GeoDjango basic apps](https://code.google.com/archive/p/geodjango-basic-apps). [^2]

> **Note**
>
> 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:

- [Installera PostGIS](/sv/5.2/ref/contrib/gis/install/postgis/)
- installera/spatialite

### Skapa ett nytt projekt

Använd standardskriptet `django-admin` för att skapa ett projekt som heter `geodjango`:

```console
$ django-admin startproject geodjango
```

*Windows*

```doscon
...\> django-admin startproject geodjango
```

Detta kommer att initiera ett nytt projekt. Nu skapar du en Django-applikation `world` inom `geodjango`-projektet:

```console
$ cd geodjango
$ python manage.py startapp world
```

*Windows*

```doscon
...\> 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`](/sv/5.2/ref/settings/#std-setting-INSTALLED_APPS) så att den inkluderar [`django.contrib.admin`](/sv/5.2/ref/contrib/admin/#module-django.contrib.admin), [`django.contrib.gis`](/sv/5.2/ref/contrib/gis/#module-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

Uppgifterna om världsgränserna finns i denna .  Skapa en `data`-katalog i applikationen `world`, ladda ner data om världsgränser och packa upp den. På GNU/Linux-plattformar använder du följande kommandon:

```console
$ 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 ../..
```

*Windows*

```doscon
...\> 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 World Borders innehåller en uppsättning datafiler som kollektivt kallas en ”ESRI Shapefile”, ett av de mest populära geospatiala dataformaten.  När den packas upp innehåller datasetet world borders filer med följande tillägg:

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

```console
$ 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)
```

*Windows*

```doscon
...\> 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` berättar för oss att shapefilen har ett lager och att detta lager innehåller polygondata.  För att ta reda på mer anger vi skiktnamnet och använder alternativet `-so` för att bara få den viktiga sammanfattande informationen:

```console
$ 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)
```

*Windows*

```doscon
...\> 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 här detaljerade sammanfattningsinformationen anger antalet funktioner i skiktet (246), de geografiska gränserna för data, det rumsliga referenssystemet (”SRS WKT”) samt typinformation för varje attributfält. Till exempel: `FIPS: String (2.0)` anger att teckenfältet `FIPS` har en maximal längd på 2. På samma sätt är `LON: Real (8.3)` ett fält med flyttal som rymmer maximalt 8 siffror med 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 rumsliga referenssystemet för geometriska fält är WGS84 (vilket innebär att  är 4326) - med andra ord är fältkoordinaterna i par av longitud och latitud i enheter av grader.  Om du vill använda ett annat koordinatsystem anger du SRID för geometrifältet 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:

```console
$ python manage.py makemigrations
Migrations for 'world':
  world/migrations/0001_initial.py:
    + Create model WorldBorder
```

*Windows*

```doscon
...\> 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`:

```console
$ python manage.py sqlmigrate world 0001
```

*Windows*

```doscon
...\> py manage.py sqlmigrate world 0001
```

Detta kommando bör ge följande resultat:

```sql
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`](/sv/5.2/ref/django-admin/#django-admin-migrate) för att skapa denna tabell i databasen:

```console
$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, world
Running migrations:
  ...
  Applying world.0001_initial... OK
```

*Windows*

```doscon
...\> 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

I det här avsnittet visas hur du importerar shapefilen med världsgränser till databasen via GeoDjango-modeller med hjälp av [LayerMapping verktyg för dataimport](/sv/5.2/ref/contrib/gis/layermapping/).

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](https://gdal.org/programs/ogr2ogr.html): Ett kommandoradsverktyg som ingår i GDAL och som kan importera många vektordataformat till PostGIS-, MySQL- och Oracle-databaser.
- [shp2pgsql](https://postgis.net/docs/using_postgis_dbmanagement.html#shp2pgsql_usage): Detta verktyg som ingår i PostGIS importerar ESRI shapefiler till PostGIS.

### GDAL-gränssnitt

Tidigare använde du `ogrinfo` för att undersöka innehållet i shapefilen för världsgränser.  GeoDjango innehåller också ett pythoniskt 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:

```console
$ python manage.py shell
```

*Windows*

```doscon
...\> py manage.py shell
```

Om du hämtade data från [Världsgränser](#worldborders) tidigare i handledningen kan du bestämma dess sökväg med hjälp av Pythons [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path):

```pycon
>>> 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`](/sv/5.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.DataSource)-gränssnitt:

```pycon
>>> 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:

```pycon
>>> 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:

```pycon
>>> print(lyr.geom_type)
Polygon
>>> print(len(lyr))
246
```

> **Note**
>
> Tyvärr tillåter inte dataformatet shapefile någon större specificitet när det gäller geometrityper.  Denna shapefil, liksom många andra, innehåller faktiskt `MultiPolygon`-geometrier, inte polygoner. Det är viktigt att använda en mer allmän fälttyp i modeller: en GeoDjango `MultiPolygonField` accepterar en `Polygon` geometri, men en `PolygonField` accepterar inte en geometri av typen `MultiPolygon`.  Det är därför som modellen `WorldBorder` som definieras ovan använder en `MultiPolygonField`.

[`Layer`](/sv/5.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.Layer) kan också ha ett rumsligt referenssystem associerat med sig.  Om det gör det kommer attributet `srs` att returnera ett [`SpatialReference`](/sv/5.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.SpatialReference)-objekt:

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

Dessutom stöder shapefiler även attributfält som kan innehålla ytterligare data.  Här är fälten på World Borders-skiktet:

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

```pycon
>>> 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`](/sv/5.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.Layer)-objekt kan skivas:

```pycon
>>> 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:

```pycon
>>> feat = lyr[234]
>>> print(feat.get("NAME"))
San Marino
```

Gränsgeometrier kan exporteras som WKT och GeoJSON:

```pycon
>>> 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 ordlistan `world_mapping` motsvarar ett fält i modellen `WorldBorder`.  Värdet är namnet på det shapefile-fält som data kommer att laddas från.
- Nyckeln `mpoly` för geometrifältet är `MULTIPOLYGON`, den geometrityp som GeoDjango kommer att importera fältet som.  Även enkla polygoner i shapefilen kommer automatiskt att konverteras till samlingar innan de läggs in i databasen.
- Sökvägen till shapefilen är inte absolut - med andra ord, om du flyttar programmet `world` (med underkatalogen `data`) till en annan plats kommer skriptet fortfarande att fungera.
- Nyckelordet `transform` är inställt på `False` eftersom data i shapefilen inte behöver konverteras - de finns redan i WGS84 (SRID=4326).

Därefter anropar du Django-skalet från projektkatalogen `geodjango`:

```console
$ python manage.py shell
```

*Windows*

```doscon
...\> py manage.py shell
```

Därefter importerar du modulen `load`, anropar rutinen `run` och ser `LayerMapping` göra jobbet:

```pycon
>>> from world import load
>>> load.run()
```

### Prova `ogrinspect`

Nu när du har sett hur man definierar geografiska modeller och importerar data med [LayerMapping verktyg för dataimport](/sv/5.2/ref/contrib/gis/layermapping/), är det möjligt att ytterligare automatisera denna process med hjälp av hanteringskommandot [`ogrinspect`](/sv/5.2/ref/contrib/gis/commands/#django-admin-ogrinspect).  Kommandot [`ogrinspect`](/sv/5.2/ref/contrib/gis/commands/#django-admin-ogrinspect) introspekterar en GDAL-stödd vektordatakälla (t.ex. en shapefil) och genererar automatiskt en modelldefinition och en `LayerMapping`-ordbok.

Den allmänna användningen av kommandot går till på följande sätt:

```console
$ python manage.py ogrinspect [options] <data_source> <model_name> [options]
```

*Windows*

```doscon
...\> 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 det namn 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:

```console
$ python manage.py ogrinspect world/data/TM_WORLD_BORDERS-0.3.shp WorldBorder \
    --srid=4326 --mapping --multi
```

*Windows*

```doscon
...\> 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=4326` anger SRID för det geografiska fältet.
- Alternativet `--mapping` säger till `ogrinspect` att även generera en mappningsordbok för användning med [`LayerMapping`](/sv/5.2/ref/contrib/gis/layermapping/#django.contrib.gis.utils.LayerMapping).
- Alternativet `--multi` anges så att det geografiska fältet är en [`MultiPolygonField`](/sv/5.2/ref/contrib/gis/model-api/#django.contrib.gis.db.models.MultiPolygonField) istället för bara en [`PolygonField`](/sv/5.2/ref/contrib/gis/model-api/#django.contrib.gis.db.models.PolygonField).

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 rumsliga uppslagningar till Django ORM.  Du kan till exempel hitta det land i tabellen `WorldBorder` som innehåller en viss punkt.  Starta först upp hanteringsskalet:

```console
$ python manage.py shell
```

*Windows*

```doscon
...\> py manage.py shell
```

Nu ska du definiera en intressepunkt [^3]:

```pycon
>>> pnt_wkt = "POINT(-95.3385 29.7245)"
```

Strängen `pnt_wkt` representerar punkten på -95,3385 graders longitud, 29,7245 graders latitud.  Geometrin är i ett format som kallas Well Known Text (WKT), en standard som utfärdats av Open Geospatial Consortium (OGC). [^4] Importera modellen `WorldBorder` och utför en `contains`-sökning med `pnt_wkt` som parameter:

```pycon
>>> from world.models import WorldBorder
>>> WorldBorder.objects.filter(mpoly__contains=pnt_wkt)
<QuerySet [<WorldBorder: United States>]>
```

Här hämtade du en `QuerySet` med bara en modell: USA:s gräns (precis vad du förväntar dig).

På samma sätt kan du också använda ett [GEOS geometriobjekt](/sv/5.2/ref/contrib/gis/geos/). Här kan du kombinera den rumsliga `intersects`-uppslagningen med `get`-metoden för att bara hämta `WorldBorder`-instansen för San Marino istället för en queryset:

```pycon
>>> from django.contrib.gis.geos import Point
>>> pnt = Point(12.4604, 43.9420)
>>> WorldBorder.objects.get(mpoly__intersects=pnt)
<WorldBorder: San Marino>
```

Uppslagningarna `contains` och `intersects` är bara en delmängd av de tillgängliga frågorna - [GeoDjango databas API](/sv/5.2/ref/contrib/gis/db-api/)-dokumentationen innehåller mer.

### Automatiska rumsliga omvandlingar

När du gör rumsliga frågor omvandlar GeoDjango automatiskt geometrier om de är i ett annat koordinatsystem.  I följande exempel kommer koordinaterna att uttryckas i , ett koordinatsystem som är specifikt för södra Texas **endast** och i enheter av **meter**, inte grader:

```pycon
>>> 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:

```pycon
>>> 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å:

```pycon
>>> 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](/sv/5.2/topics/db/sql/) måste du omsluta dina geometrifält så att fältvärdet kan identifieras av GEOS:
>
> ```pycon
> >>> 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 laddar geometrier i en standardiserad textuell representation.  När geometrifältet först nås skapar GeoDjango ett [`GEOSGeometry`](/sv/5.2/ref/contrib/gis/geos/#django.contrib.gis.geos.GEOSGeometry)-objekt, som exponerar kraftfull funktionalitet, till exempel serialiseringsegenskaper för populära geospatiala format:

```pycon
>>> 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:

```pycon
>>> 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 (intersektion, skillnad, etc.). Se dokumentationen för [Geografiska databasfunktioner](/sv/5.2/ref/contrib/gis/functions/).

## Placera dina data på kartan

### Geografisk administratör

[Djangos admin-applikation](/sv/5.2/ref/contrib/admin/) 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](https://openlayers.org/)).

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:

```console
$ python manage.py createsuperuser
```

*Windows*

```doscon
...\> py manage.py createsuperuser
```

Starta sedan upp Django-utvecklingsservern:

```console
$ python manage.py runserver
```

*Windows*

```doscon
...\> 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`](/sv/5.2/ref/contrib/gis/admin/#django.contrib.gis.admin.GISModelAdmin) använder GeoDjango ett [OpenStreetMap](https://www.openstreetmap.org/)-lager i admin. Detta ger mer sammanhang (inklusive detaljer om gator och genomfartsleder) än vad som är tillgängligt med [`ModelAdmin`](/sv/5.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin) (som använder WMS-datasetet [Vector Map Level 0](http://web.archive.org/web/20201024202709/https://earth-info.nga.mil/publications/vmap0.html) som finns hos [OSGeo](https://www.osgeo.org/)).

PROJ datumskiftesfiler måste installeras (se [PROJ installationsinstruktioner](/sv/5.2/ref/contrib/gis/install/geolibs/#proj4) 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**

[^1]: Ett särskilt tack till Bjørn Sandvik på [mastermaps.net](https://mastermaps.net/) för tillhandahållande och underhåll av detta dataset.

[^2]: GeoDjango basic apps är skriven av Dane Springmeyer, Josh Livni och Christopher Schmidt.

[^3]: Denna punkt är [University of Houston Law Center](https://www.law.uh.edu/).

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