Search code examples
pythondjangogeodjangoogr

Geodjango Import Shapefile with LayerMapping and OGR


I am trying to load a shapefile into Django

My folder

vnm_polbn_adm3_2014_pdc.dbf
vnm_polbn_adm3_2014_pdc.prj
vnm_polbn_adm3_2014_pdc.qpj
vnm_polbn_adm3_2014_pdc.shp
vnm_polbn_adm3_2014_pdc.shx

When I'm running this:

simon@DESKTOP-V82N14G:/mnt/c/WINDOWS/system32/poc_dashboard/pocdash$  ogrinfo -ro -so  testdjango/data/vnm_polbn_adm3_2014_pdc.shp
INFO: Open of `testdjango/data/vnm_polbn_adm3_2014_pdc.shp'
      using driver `ESRI Shapefile' successful.
1: vnm_polbn_adm3_2014_pdc (Polygon)

When I use the python shell to run my code:

python manage.py shell
from testdjango import load_layer
load_layer.run()

It returns me :

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/mnt/c/WINDOWS/system32/poc_dashboard/pocdash/testdjango/load_layer.py", line 27, in run
    lm = LayerMapping(Adm3_names, adm3_name_shp, adm3_name_mapping, transform= False, encoding='iso-8859-1')
  File "/mnt/c/WINDOWS/system32/poc_dashboard/poc/lib/python3.6/site-packages/django/contrib/gis/utils/layermapping.py", line 92, in __init__
    self.ds = DataSource(data, encoding=encoding)
  File "/mnt/c/WINDOWS/system32/poc_dashboard/poc/lib/python3.6/site-packages/django/contrib/gis/gdal/datasource.py", line 74, in __init__
    raise GDALException('Could not open the datasource at "%s"' % ds_input)
django.contrib.gis.gdal.error.GDALException: Could not open the datasource at "/mnt/c/WINDOWS/system32/poc_dashboard/pocdash/testdjango/testdjango/data/vnm_polbn_adm3_2014_pdc.shp"

Is it something wrong with my code or something wrong with my shapefile? I attached the file here

import os
from django.contrib.gis.utils import LayerMapping
from django.contrib.gis.db import models
from .models import Adm3_names

adm3_name_mapping = {
    'gid': 'gid',
    'adm1_code': 'adm1_code',
    'adm1_name': 'adm1_name',
    'adm2_code': 'adm2_code',
    'adm2_name': 'adm2_name',
    'adm3_code': 'adm3_code',
    'adm3_name': 'adm3_name',
    'adm3_statu': 'adm3_statu',
    'pop': 'pop',
    'pop_0to14': 'pop_0to14',
    'pop_65plus': 'pop_65plus',
    'hh': 'hh',
    'shape_leng': 'shape_leng',
    'shape_area': 'shape_area',
    'geom': 'MULTIPOLYGON',
}

adm3_name_shp = os.path. abspath(os.path.join(os.path.dirname(__file__),'testdjango/data/vnm_polbn_adm3_2014_pdc.shp'))

def run(verbose=True):
    lm = LayerMapping(Adm3_names, adm3_name_shp, adm3_name_mapping, transform= False, encoding='iso-8859-1')
    lm.save(strict=True,verbose=verbose)

https://docs.djangoproject.com/en/2.2/ref/contrib/gis/layermapping/


Solution

  • As we found out from the comments, the problem was the creation of the adm3_name_shp which adds an extra testdjango folder to the path:

    Change this:

    adm3_name_shp = os.path.abspath(os.path.join(os.path.dirname(__file__),'testdjango/data/vnm_polbn_adm3_2014_pdc.shp'))
    

    to this:

    adm3_name_shp = os.path.abspath(os.path.join(os.path.dirname(__file__),'data/vnm_polbn_adm3_2014_pdc.shp'))
    

    Another tip you should consider is that the os.path.abspath calls the os.path.normpath in the background and that is what transforms your path to the correct OS path (either with \ for Windows or / for Linux etc.):

    Normalize a pathname by collapsing redundant separators and up-level references so that A//B, A/B/, A/./B and A/foo/../B all become A/B. This string manipulation may change the meaning of a path that contains symbolic links. On Windows, it converts forward slashes to backward slashes. To normalize case, use normcase().

    So you can replace the abspath with normpath but this is optional.