GEODjango (django에서 geographic 다루기)

사전 설치


GDAL 이용한 shp 다루기

ogrinfo world\data\TM_WORLD_BORDERS-0.3.shp // shp파일 또는 다른 벡터 소스에 대한 info를 보여줌

ogrinfo -so world\data\TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3 // -so option을 통해 중요한 summary 정보를 조회


Geomgraphic Models

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
  • migrate 실행
  • py manage.py makemigrations //datebase migration 생성
  • py manage.py sqlmigrate world 0001 //migrate sql 조회
  • py manage.py migrate //migrate 실행


GDAL Interface

py manage.py shell
from pathlib import Path
import world
world_shp = Path(world.__file__).resolve().parent / 'data' / 'TM_WORLD_BORDERS-0.3.shp'
from django.contrib.gis.gdal import DataSource
ds = DataSource(str(world_shp))
print(ds)               //datasource 조회
print(len(ds))          //1
lyr = ds[0]
print(lyr)              //TM_WORLD_BORDERS-0.3
print(lyr.geom_type)    //Polygon
print(len(lyr))         //246
srs = lyr.srs           
print(srs)              //srs
srs.proj4               //proj4
print(lyr.fields)       //fields
[fld.__name__ for fld in lyr.field_types]
for feat in lyr:
...    print(feat.get('NAME'), feat.geom.num_points)    //iterate feature
lyr[0:2]                //object slice
feat = lyr[234]
print(feat.get('NAME')) //San Marino
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

world 프로젝트에 load.py 생성

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, str(world_shp), world_mapping, transform=False)
    lm.save(strict=True, verbose=verbose)


py manage.py shell
from world import load
load.run()


  • ogrinspect
  • layer mapping 자동화
py manage.py ogrinspect world\data\TM_WORLD_BORDERS-0.3.shp WorldBorder --srid=4326 --mapping --multi

Spatial Queries

py manage.py shell

pnt_wkt = 'POINT(-95.3385 29.7245)'

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

from django.contrib.gis.geos import Point
pnt = Point(12.4604, 43.9420)
WorldBorder.objects.get(mpoly__intersects=pnt)

from django.contrib.gis.geos import GEOSGeometry, Point
pnt = Point(954158.1, 4215137.1, srid=32140)
pnt = GEOSGeometry('SRID=32140;POINT(954158.1 4215137.1)')

qs = WorldBorder.objects.filter(mpoly__intersects=pnt)
print(qs.query)


  • Raw quries
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'))


  • Lazy Geometries
sm = WorldBorder.objects.get(name='San Marino')
sm.mpoly  // <MultiPolygon object at 0x24c6798>
sm.mpoly.wkt // MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ...
sm.mpoly.wkb // <read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40>
sm.mpoly.geojson //'{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...

함수


  • Geographic Admin

Django’s admin application의 확장으로 geometry fields의 편집을 제공한다.

world/admin.py

from django.contrib.gis import admin
from .models import WorldBorder

admin.site.register(WorldBorder, admin.OSMGeoAdmin)

geodjango/urls.py

from django.contrib.gis import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
]
py manage.py createsuperuser

py manage.py runserver

출처

https://docs.djangoproject.com/en/3.1/ref/contrib/gis/install/ https://docs.djangoproject.com/en/3.1/ref/contrib/gis/tutorial/