Ceci est le dernier article de notre série sur les migrations Django :
- Partie 1 :Migrations Django - Introduction
- Partie 2 :Approfondir les migrations
- Partie 3 :migrations de données (article actuel)
- Vidéo :Migrations Django 1.7 - Introduction
De retour.
Les migrations servent principalement à maintenir à jour le modèle de données de votre base de données, mais une base de données est plus qu'un simple modèle de données. Plus particulièrement, c'est aussi une grande collection de données. Ainsi, toute discussion sur les migrations de bases de données ne serait pas complète sans parler également des migrations de données.
Mis à jour le 12 février 2015 :Modification de la migration des données pour rechercher un modèle dans le registre de l'application.
Définition des migrations de données
Les migrations de données sont utilisées dans un certain nombre de scénarios. Deux d'entre eux sont très populaires :
- Lorsque vous souhaitez charger des "données système" dont votre application dépend pour fonctionner correctement.
- Lorsqu'une modification apportée à un modèle de données oblige à modifier les données existantes.
Notez que le chargement de données factices pour les tests ne figure pas dans la liste ci-dessus. Vous pouvez utiliser des migrations pour ce faire, mais les migrations sont souvent exécutées sur des serveurs de production, vous ne voulez donc probablement pas créer un tas de données de test factices sur votre serveur de production.
Exemples
Dans la continuité du projet Django précédent, à titre d'exemple de création de «données système», créons des prix historiques du bitcoin. Les migrations Django vont nous aider, en créant un fichier de migration vide et en le plaçant au bon endroit si nous tapons :
$ ./manage.py makemigrations --empty historical_data
Cela devrait créer un fichier appelé historical_data/migrations/003_auto<date_time_stamp>.py
. Changeons le nom en 003_load_historical_data.py
puis ouvrez-le. Vous aurez une structure par défaut qui ressemble à :
# encoding: utf8
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('historical_data', '0002_auto_20140710_0810'),
]
operations = [
]
Vous pouvez voir qu'il a créé une structure de base pour nous, et même inséré les dépendances. C'est utile. Maintenant, pour effectuer des migrations de données, utilisez le RunPython
opération de migration :
# encoding: utf8
from django.db import models, migrations
from datetime import date
def load_data(apps, schema_editor):
PriceHistory = apps.get_model("historical_data", "PriceHistory")
PriceHistory(date=date(2013,11,29),
price=1234.00,
volume=354564,
total_btc=12054375,
).save()
PriceHistory(date=date(2012,11,29),
price=12.15,
volume=187947,
total_btc=10504650,
).save()
class Migration(migrations.Migration):
dependencies = [
('historical_data', '0002_auto_20140710_0810'),
]
operations = [
migrations.RunPython(load_data)
]
Nous commençons par définir la fonction load_data
qui - vous l'avez deviné - charge les données.
Pour une vraie application, nous voudrons peut-être aller sur blockchain.info et récupérer la liste complète des prix historiques, mais nous en avons juste mis quelques-uns là-dedans pour montrer comment fonctionne la migration.
Une fois que nous avons la fonction, nous pouvons l'appeler depuis notre RunPython
opération, puis cette fonction sera exécutée lorsque nous exécuterons ./manage.py migrate
depuis la ligne de commande.
Notez la ligne :
PriceHistory = apps.get_model("historical_data", "PriceHistory")
Lors de l'exécution de migrations, il est important d'obtenir la version de notre PriceHistory
modèle qui correspond au point de la migration où vous vous trouvez. Lorsque vous exécutez des migrations, votre modèle (PriceHistory
) peut changer, si par exemple vous ajoutez ou supprimez une colonne lors d'une migration ultérieure. Cela peut entraîner l'échec de la migration de vos données, sauf si vous utilisez la ligne ci-dessus pour obtenir la version correcte du modèle. Pour en savoir plus, veuillez consulter le commentaire ici.
C'est sans doute plus de travail que d'exécuter syncdb
et le faire charger un appareil. En fait, les migrations ne respectent pas les appareils - ce qui signifie qu'ils ne les chargeront pas automatiquement pour vous comme syncdb
le ferait.
Cela est principalement dû à la philosophie.
Bien que vous puissiez utiliser des migrations pour charger des données, elles concernent principalement la migration de données et/ou de modèles de données. Nous avons montré un exemple de chargement de données système, principalement parce qu'il s'agit d'une explication simple de la façon dont vous configureriez une migration de données, mais souvent, les migrations de données sont utilisées pour des actions plus complexes comme la transformation de vos données pour correspondre au nouveau modèle de données.
Un exemple pourrait être si nous décidions de commencer à stocker les prix de plusieurs échanges au lieu d'un seul, afin que nous puissions ajouter des champs comme price_gox
, price_btc
, etc., nous pourrions alors utiliser une migration pour déplacer toutes les données du price
colonne au price_btc
colonne.
En général, lorsqu'il s'agit de migrations dans Django 1.7, il est préférable de considérer le chargement des données comme un exercice distinct de la migration de la base de données. Si vous souhaitez continuer à utiliser/charger des projecteurs, vous pouvez utiliser une commande telle que :
$ ./manage.py loaddata historical_data/fixtures/initial_data.json
Cela chargera les données de l'appareil dans la base de données.
Cela ne se produit pas automatiquement comme avec une migration de données (ce qui est probablement une bonne chose), mais la fonctionnalité est toujours là ; il n'a pas été perdu, alors n'hésitez pas à continuer à utiliser des luminaires si vous en avez besoin. La différence est que maintenant vous chargez des données avec des projecteurs quand vous en avez besoin. C'est quelque chose à garder à l'esprit si vous utilisez des appareils pour charger des données de test pour vos tests unitaires.
Conclusion
Ceci, ainsi que les deux articles précédents, couvre les scénarios les plus courants que vous rencontrerez lors de l'utilisation des migrations. Il existe de nombreux autres scénarios, et si vous êtes curieux et que vous voulez vraiment vous plonger dans les migrations, le meilleur endroit où aller (autre que le code lui-même) est la documentation officielle.
C'est le plus à jour et fait un assez bon travail pour expliquer comment les choses fonctionnent. S'il existe un scénario plus complexe dont vous aimeriez voir un exemple, veuillez nous en informer en commentant ci-dessous.
N'oubliez pas que dans le cas général, vous avez affaire soit :
-
Migrations de schéma : Modification de la structure de la base de données ou des tables sans modification des données. C'est le type le plus courant, et Django peut généralement créer automatiquement ces migrations pour vous.
-
Migrations de données : Modification des données ou chargement de nouvelles données. Django ne peut pas les générer pour vous. Ils doivent être créés manuellement à l'aide du
RunPython
migration.
Choisissez donc la migration qui vous convient, exécutez makemigrations
puis assurez-vous simplement de mettre à jour vos fichiers de migration chaque fois que vous mettez à jour votre modèle, et c'est plus ou moins tout. Cela vous permettra de conserver vos migrations stockées avec votre code dans git et de vous assurer que vous pouvez mettre à jour la structure de votre base de données sans avoir à perdre de données.
Bonne migration !