# Documentation Django 3.1.9.dev

# Utilitaire d’importation de données `LayerMapping`

La classe `LayerMapping` fournit une manière de faire correspondre du contenu provenant de fichiers de données spatiales (par ex. des fichiers shape) avec des modèles GeoDjango.

Cet utilitaire a été fabriqué à partir des besoins personnels de son auteur qui a ressenti le besoin d’éliminer de la répétition de code provenant de l’extraction d’objets géométriques et de champs de données à partir d’une couche vectorielle, de les convertir dans un autre système de coordonnées (par ex. WGS84) et de les insérer dans un modèle GeoDjango.

Note

L’utilisation de `LayerMapping` nécessite GDAL.

Avertissement

Les sources de données GIS comme les fichiers shape peuvent être très volumineuses. Si vous constatez que `LayerMapping` utilise trop de mémoire, définissez `DEBUG` à `False` dans vos réglages. Lorsque `DEBUG` est défini à `True`, Django journalise automatiquement chaque requête SQL, et lorsque des instructions SQL contiennent des géométries, cela peut consommer plus de mémoire que d’habitude.

## Exemple

1. Vous avez besoin d’une source de données prise en charge par GDAL, comme un fichier shape (nous utiliserons ici un fichier shape simple formé de trois polygones) :

       >>> from django.contrib.gis.gdal import DataSource
       >>> ds = DataSource('test_poly.shp')
       >>> layer = ds[0]
       >>> print(layer.fields) # Exploring the fields in the layer, we only want the 'str' field.
       ['float', 'int', 'str']
       >>> print(len(layer)) # getting the number of features in the layer (should be 3)
       3
       >>> print(layer.geom_type) # Should be 'Polygon'
       Polygon
       >>> print(layer.srs) # WGS84 in WKT
       GEOGCS["GCS_WGS_1984",
           DATUM["WGS_1984",
               SPHEROID["WGS_1984",6378137,298.257223563]],
           PRIMEM["Greenwich",0],
           UNIT["Degree",0.017453292519943295]]

2. Nous définissons ensuite le modèle Django correspondant (assurez-vous d’utiliser `migrate`) :

       from django.contrib.gis.db import models

       class TestGeo(models.Model):
           name = models.CharField(max_length=25) # corresponds to the 'str' field
           poly = models.PolygonField(srid=4269) # we want our model in a different SRID

           def __str__(self):
               return 'Name: %s' % self.name

3. Utilisez `LayerMapping` pour extraire tous les éléments et les placer dans la base de données :

       >>> from django.contrib.gis.utils import LayerMapping
       >>> from geoapp.models import TestGeo
       >>> mapping = {'name' : 'str', # The 'name' model field maps to the 'str' layer field.
                      'poly' : 'POLYGON', # For geometry fields use OGC name.
                      } # The mapping is a dictionary
       >>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping)
       >>> lm.save(verbose=True) # Save the layermap, imports the data.
       Saved: Name: 1
       Saved: Name: 2
       Saved: Name: 3

Dans cet exemple, `LayerMapping` a transformé les trois objets géométriques du fichier shape de leur système de référence spatiale original (WGS84) vers le système de référence spatiale du modèle GeoDjango (NAD83). Si aucun système de référence spatiale n’avait été défini dans la couche, il aurait fallu employer le paramètre `source_srs` avec un objet `SpatialReference` pour en définir un.

## API de `LayerMapping`

class `LayerMapping`(model, data_source, mapping, layer=0, source_srs=None, encoding=None, transaction_mode='commit_on_success', transform=True, unique=True, using='default')

Voici les paramètres positionnels et nommés pouvant être utilisés durant la création d’instances d’objets `LayerMapping`.

Paramètre | Description
--- | ---
`model` | Le modèle géographique, pas une instance.
`data_source` | Le chemin vers le fichier de source de données pris en charge par OGR (par ex. un fichier shape). Accepte aussi des instances de `django.contrib.gis.gdal.DataSource`.
`mapping` | Un dictionnaire : les clés sont des chaînes correspondant aux champs de modèle et les valeurs correspondent aux noms de champs des éléments OGR ou, dans le cas où le champ de modèle est géographique, au type géométrique OGR, par ex. `'POINT'`, `'LINESTRING'`, `'POLYGON'`.

Paramètres nommés |
--- | ---
`layer` | L’indice de la couche à utiliser dans la source de données (0 par défaut).
`source_srs` | Utile pour définir manuellement le système de référence spatiale de la source (par exemple pour les fichiers shape sans fichier `'.prj'` annexe). Les valeurs acceptées sont un code SRID nombre entier, une chaîne WKT ou PROJ.4, ou un objet `django.contrib.gis.gdal.SpatialReference`.
`encoding` | Définit le codage du jeu de caractères du contenu textuel dans la source de données OGR. Par exemple, `'latin-1'`, `'utf-8'` et `'cp437'` sont tous des paramètres de codage valables.
`transaction_mode` | Peut être `'commit_on_success'` (par défaut) ou `'autocommit'`.
`transform` | Quand ce paramètre vaut `False`, les transformations de coordonnées sont désactivées. En d’autres termes, les objets géométriques sont insérés dans la base de données exactement tels qu’ils sont lus à partir de leur source de données.
`unique` | Ce paramètre peut contenir un nom ou un tuple de noms du modèle concerné afin que les instances créées soient uniques pour le ou les noms de champs donnés. Les objets géométriques de chaque élément seront ajoutés à la collection associée au modèle unique. Le mode de transaction est forcé à `'autocommit'`.
`using` | Définit la base de données à utiliser lors de l’importation de données spatiales. La valeur par défaut est `'default'`.

### Paramètres nommés de `save()`

`LayerMapping.``save`(verbose=False, fid_range=False, step=False, progress=False, silent=False, stream=sys.stdout, strict=False)

La méthode `save()` accepte aussi des paramètres nommés. Ils sont utilisés pour contrôler la journalisation en sortie, le traitement des erreurs et pour l’importation de sous-ensembles d’éléments.

Paramètre nommé de `save` | Description
--- | ---
`fid_range` | Peut être défini avec une segmentation ou un tuple `(début, fin)` d’identifiants d’éléments dans la source de données. Autrement dit, ce paramètre permet d’importer un sous-ensemble d’éléments de manière sélective dans la source de données géographique.
`progress` | Si ce paramètre contient `True`, des informations de détail sont affichées pour indiquer le nombre d’éléments traités et enregistrés. Par défaut, des informations de progression sont affichées après chaque groupe de 1000 éléments traités. Ce comportement peut être surchargé en attribuant un nombre entier à ce paramètre pour définir l’intervalle souhaité.
`silent` | Par défaut, les notifications d’erreurs non fatales sont affichées sur `sys.stdout`, mais ce paramètre booléen peut être défini pour désactiver ces notifications.
`step` | Lorsqu’il contient un nombre entier, définit l’intervalle d’enregistrement par transaction. Par exemple, si `step=1000`, une transaction est validée (commit) après le 1000e élément, après le 2000e élément, etc.
`stream` | Les informations de progression sont écrites sur ce flux fichier. Par défaut, il s’agit de `sys.stdout`, mais tout objet comportant une méthode `write` convient également.
`strict` | Si ce paramètre vaut `True`, l’importation d’éléments dans le modèle s’arrête dès qu’une première erreur est rencontrée. Avec le comportement par défaut (`False`), le script tente de poursuivre.
`verbose` | Si défini à `True`, des informations s’affichent après chaque enregistrement de modèle dans la base de données.

## Dépannage

### Consommation excessive de mémoire

Comme relevé dans l’avertissement en haut de cette section, Django mémorise toutes les requêtes SQL lorsque `DEBUG=True`. Définissez `DEBUG=False` dans vos réglages pour empêcher une consommation excessive de la mémoire lorsque vous exécutez les scripts `LayerMapping`.

### MySQL : erreur `max_allowed_packet`

Si vous rencontrez l’erreur suivante lorsque vous utilisez la fonctionnalité `LayerMapping` avec MySQL :

    OperationalError: (1153, "Got a packet bigger than 'max_allowed_packet' bytes")

La solution est alors d’augmenter la valeur du paramètre `max_allowed_packet` dans votre configuration de MySQL. Par exemple, la valeur par défaut peut être parfois aussi basse qu’un mégaoctet. Ce paramètre peut être modifié dans le fichier de configuration de MySQL (`my.cnf`) à la section `[mysqld]`:

    max_allowed_packet = 10M