Instantanés¶
Voir aussi
Qu’est-ce qu’un instantané (fixture en anglais) ?¶
Un instantané est un ensemble de fichiers contenant du contenu sérialisé de base de données. Chaque instantané possède un nom unique et les fichiers composant l’instantané peuvent être distribués dans plusieurs répertoires et plusieurs applications.
Comment produire un instantané¶
Les instantanés peuvent être générés par la commande manage.py dumpdata
. Il est aussi possible de produire des instantanés personnalisés en utilisant directement les outils de sérialisation ou même en les écrivant à la main.
Comment utiliser un instantané¶
Les instantanés peuvent être utilisés pour préremplir la base de données avec des données pour les tests:
class MyTestCase(TestCase):
fixtures = ["fixture-label"]
ou pour fournir des données initiales en utilisant la commande loaddata
:
django-admin loaddata <fixture label>
Emplacements de recherche des instantanés¶
Django recherche les instantanés à ces emplacements :
- Dans le répertoire
fixtures
de chaque application installée - Dans tout répertoire mentionné dans le réglage
FIXTURE_DIRS
- Dans le chemin explicitement contenu dans le nom de l’instantané
Django va charger tous les instantanés qu’il trouve aux emplacements indiqués par les noms d’instantanés. Si un nom d’instantané indiqué possède une extension de fichier, seuls des instantanés de ce type seront chargés. Par exemple :
django-admin loaddata mydata.json
ne charge que les instantanés JSON nommés mydata
. L’extension d’instantané doit correspondre au nom enregistré d’un sérialiseur (par ex. json
ou xml
).
Si vous omettez l’extension, Django recherche tous les types d’instantané disponibles pour chaque instantané trouvé. Par exemple :
django-admin loaddata mydata
recherche tout instantané ou type d’instantané nommé mydata
. Si un répertoire d’instantané contient mydata.json
, cet instantané serait chargé comme instantané JSON.
Les noms d’instantanés peuvent contenir une partie « chemin ». Ces répertoires sont alors inclus dans le chemin de recherche. Par exemple :
django-admin loaddata foo/bar/mydata.json
recherche <étiquette_app>/fixtures/foo/bar/mydata.json
pour chaque application installée, <nom_rép>/foo/bar/mydata.json
pour chaque répertoire dans FIXTURE_DIRS
ainsi que le chemin littéral foo/bar/mydata.json
.
Ordre de chargement des instantanés¶
Plusieurs instantanés peuvent être indiqués dans la même invocation. Par exemple :
django-admin loaddata mammals birds insects
ou dans une classe de cas de tests :
class AnimalTestCase(TestCase):
fixtures = ["mammals", "birds", "insects"]
L’ordre dans lequel sont chargés les instantanés suit l’ordre dans lequel ils sont indiqués, que ce soit lors de l’utilisation de la commande d’administration ou quand ils sont mentionnés dans une classe de cas de tests comme démontré plus haut.
Dans ces exemples, tous les instantanés nommés mammals
dans toutes les applications (dans l’ordre d’apparition des applications dans INSTALLED_APPS
) seront chargés en premier. Puis, tous les instantanés birds
seront chargés, suivis par tous les instantanés insects
.
Sachez que si le moteur de base de données gère les contraintes de lignes, celles-ci seront vérifiées à la fin de la transaction. Toute relation traversant les instantanés peut aboutir à une erreur de chargement si la configuration de base de données ne prend pas en charge le contrôle différé des contraintes (référez-vous à la documentation de MySQL pour un exemple).
Comment les instantanés sont enregistrés en base de données¶
Lorsque des fichiers d’instantanés sont traités, les données sont enregistrées telles quelles dans la base de données. Les méthodes save()
définies dans les modèles ne sont pas appelées et les éventuels signaux pre_save
ou post_save
sont appelés avec raw=True
car l’instance ne contient que les attributs locaux du modèle. Il est par exemple imaginable de désactiver les gestionnaires accédant aux champs liés absents lors du chargement des instantanés, car une exception serait générée dans le cas contraire :
from django.db.models.signals import post_save
from .models import MyModel
def my_handler(**kwargs):
# disable the handler during fixture loading
if kwargs["raw"]:
return
...
post_save.connect(my_handler, sender=MyModel)
On pourrait aussi écrire un décorateur pour encapsuler cette logique :
from functools import wraps
def disable_for_loaddata(signal_handler):
"""
Decorator that turns off signal handlers when loading fixture data.
"""
@wraps(signal_handler)
def wrapper(*args, **kwargs):
if kwargs["raw"]:
return
signal_handler(*args, **kwargs)
return wrapper
@disable_for_loaddata
def my_handler(**kwargs): ...
Il faut cependant être conscient que cette logique désactivera les signaux lors de chaque désérialisation des instantanés, pas seulement durant loaddata
.
Instantanés compressés¶
Les instantanés peuvent être compressés dans les formats zip
, gz
, bz2
, lzma
ou xz
. Par exemple :
django-admin loaddata mydata.json
recherche l’un des fichiers mydata.json
, mydata.json.zip
, mydata.json.gz
, mydata.json.bz2
, mydata.json.lzma
ou mydata.json.xz
. Le premier fichier contenu dans une archive compressée est utilisé.
Notez que si deux instantanés de même nom mais de type différent sont trouvés (par exemple si mydata.json
et mydata.xml.gz
sont trouvés dans le même répertoire d’instantanés), l’installation des instantanés est interrompue et toute donnée déjà installée par l’appel à loaddata
est retirée de la base de données.
MySQL avec MyISAM et les instantanés
Le moteur de stockage MyISAM de MySQL ne gère ni les transactions, ni les contraintes. Si vous utilisez ce moteur, les données d’instantanés ne sont pas validées et d’éventuelles données déjà chargées en base de données ne sont pas effacées dans le cas où des fichiers d’instantanés conflictuels sont trouvés.
Instantanés spécifiques à certaines bases de données¶
Si vous vous trouvez dans une configuration avec plusieurs bases de données, il se pourrait que vous vouliez charger certains instantanés dans une base de données mais pas dans l’autre. Dans cette situation, vous pouvez insérer des identifiants de base de données dans les noms des instantanés.
Par exemple, si votre réglage DATABASES
contient une base de données users
, nommez l’instantané mesdonnees.users.json
ou mesdonnees.users.json.gz
et cet instantané ne sera chargé que lorsque vous indiquez que vous souhaitez charger des données dans la base de données users
.