Using ogrinfo -so
I've found the structure of the shapefile and based on this structure I've created a model:
from django.contrib.gis.db import models
class Villages(models.Model):
.
.
.
After that I've created the load.py
as mentioned here inside the same directory of models.py
:
from pathlib import Path
from django.contrib.gis.utils import LayerMapping
from .models import Villages
villages_mapping = {
.
.
.
}
villages = Path(__file__).resolve().parent / 'gis' / 'villages.shp'
def run(verbose=True):
lm = LayerMapping(Villages, villages, villages_mapping, transform=False)
lm.save(strict=True, verbose=verbose)
Then, I try to use load.py
:
python3 manage.py shell
> from geodata import load
> load.run()
But I see this strange error:
Traceback (most recent call last): File "<console>", line 1, in
<module> File
"/home/maxdragonheart/DEV_FOLDER/Django/Enographiae/enographiae_dev/enographiae/geodata/load.py", line 32, in run
lm = LayerMapping(Villages, villages, villages_mapping, transform=False) File
"/home/maxdragonheart/DEV_FOLDER/Django/Enographiae/enographiae_dev/devenv/lib/python3.7/site-packages/django/contrib/gis/utils/layermapping.py", line 99, in __init__
self.layer = self.ds[layer] TypeError: 'PosixPath' object is not subscriptable
EDIT:
Maybe the problem is inside layermapping.py
. I've replicated the tutorial using the original code and datas and I see this:
File "<console>", line 1, in <module>
File "/home/maxdragonheart/DEV_FOLDER/Django/Singole APP/GeoDjango/webgis/tutorialgeodjango/load.py", line 23, in run
lm = LayerMapping(WorldBorder, world_shp, world_mapping, transform=False)
File "/home/maxdragonheart/DEV_FOLDER/Django/Singole APP/GeoDjango/devenv/lib/python3.7/site-packages/django/contrib/gis/utils/layermapping.py", line 100, in __init__
self.layer = self.ds[layer]
TypeError: 'PosixPath' object is not subscriptable
EDIT 2:
Using the code from Django 2.2 I've no problem to upload datas. How I can report this bug?
EDIT 3:
The problem is also in Django 3.1.3
Django documentation for LayerMapping API is not 100 % clear on a data type for path, but if you check the source code, you'll see it expects either a string or DataSource instance.
Below is the relevant code from the source code.
def __init__(self, model, data, mapping, layer=0,
source_srs=None, encoding='utf-8',
transaction_mode='commit_on_success',
transform=True, unique=None, using=None):
"""
A LayerMapping object is initialized using the given Model (not an instance),
a DataSource (or string path to an OGR-supported data file), and a mapping
dictionary. See the module level docstring for more details and keyword
argument usage.
"""
# Getting the DataSource and the associated Layer.
if isinstance(data, str):
self.ds = DataSource(data, encoding=encoding)
else:
self.ds = data
self.layer = self.ds[layer]
The comment mentions string path and later in code there is a check if data
argument is a string (path in this case) in initializes DataSource
instance with it.
Simply changing Path
to str
will fix your problem.
lm = LayerMapping(Villages, str(villages), villages_mapping, transform=False)