Recherche…


Paramètres

django-admin Détails
makemigrations <my_app> Générer des migrations pour my_app
makemigrations Générer des migrations pour toutes les applications
makemigrations --merge Résoudre les conflits de migration pour toutes les applications
makemigrations --merge <my_app> Résoudre les conflits de migration pour my_app
makemigrations --name <migration_name> <my_app> Générer une migration pour my_app avec le nom migration_name
migrate <my_app> Appliquer les migrations en attente de my_app à la base de données
migrate Appliquer toutes les migrations en attente à la base de données
migrate <my_app> <migration_name> Appliquer ou non à la migration_name
migrate <my_app> zero Inapplicable toutes les migrations dans my_app
sqlmigrate <my_app> <migration_name> Imprime le SQL pour la migration nommée
showmigrations Affiche toutes les migrations pour toutes les applications
showmigrations <my_app> Affiche toutes les migrations dans my_app

Travailler avec des migrations

Django utilise les migrations pour propager les modifications apportées à vos modèles dans votre base de données. La plupart du temps, Django peut les générer pour vous.

Pour créer une migration, exécutez:

$ django-admin makemigrations <app_name>

Cela créera un fichier de migration dans le sous-module de migration app_name . La première migration s'appellera 0001_initial.py , l'autre commencera par 0002_ , puis 0003 , ...

Si vous omettez <app_name> cela créera des migrations pour tous vos INSTALLED_APPS .

Pour propager les migrations vers votre base de données, exécutez:

$ django-admin migrate <app_name>

Pour afficher toutes vos migrations, exécutez:

$ django-admin showmigrations app_name
app_name
  [X] 0001_initial
  [X] 0002_auto_20160115_1027
  [X] 0003_somemodel
  [ ] 0004_auto_20160323_1826
  • [X] signifie que la migration a été propagée vers votre base de données
  • [ ] signifie que la migration n'a pas été propagée à votre base de données. Utilisez django-admin migrate pour le propager

Vous appelez également les migrations de retour, cela peut être fait en transmettant le nom de la migration à la migrate command . Compte tenu de la liste ci-dessus des migrations (montrée par django-admin showmigrations ):

$ django-admin migrate app_name 0002  # Roll back to migration 0002
$ django-admin showmigrations app_name
app_name
  [X] 0001_initial
  [X] 0002_auto_20160115_1027
  [ ] 0003_somemodel
  [ ] 0004_auto_20160323_1826

Migrations manuelles

Parfois, les migrations générées par Django ne sont pas suffisantes. Cela est particulièrement vrai lorsque vous souhaitez effectuer des migrations de données .

Par exemple, vous avez un tel modèle:

class Article(models.Model):
    title = models.CharField(max_length=70)

Ce modèle possède déjà des données existantes et vous souhaitez maintenant ajouter un SlugField :

class Article(models.Model):
    title = models.CharField(max_length=70)
    slug = models.SlugField(max_length=70)

Vous avez créé les migrations pour ajouter le champ, mais vous souhaitez maintenant définir le slug pour tous les articles existants, en fonction de leur title .

Bien sûr, vous pourriez faire quelque chose comme ça dans le terminal:

$ django-admin shell
>>> from my_app.models import Article
>>> from django.utils.text import slugify
>>> for article in Article.objects.all():
...     article.slug = slugify(article.title)
...     article.save()
...
>>>

Mais vous devrez le faire dans tous vos environnements (c.-à-d. Votre ordinateur de bureau, votre ordinateur portable, etc.), tous vos collègues devront le faire également, et vous devrez y réfléchir lors de la mise en scène et de la poussée. vivre.

Pour le faire une fois pour toutes, nous le ferons dans une migration. Commencez par créer une migration vide:

$ django-admin makemigrations --empty app_name

Cela créera un fichier de migration vide. Ouvrez-le, il contient un squelette de base. Disons que votre migration précédente s'appelait 0023_article_slug et que celle-ci s'appelle 0024_auto_20160719_1734 . Voici ce que nous allons écrire dans notre fichier de migration:

# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-07-19 15:34
from __future__ import unicode_literals

from django.db import migrations
from django.utils.text import slugify


def gen_slug(apps, schema_editor):
    # We can't import the Article model directly as it may be a newer
    # version than this migration expects. We use the historical version.
    Article = apps.get_model('app_name', 'Article')
    for row in Article.objects.all():
        row.slug = slugify(row.name)
        row.save()


class Migration(migrations.Migration):

    dependencies = [
        ('hosting', '0023_article_slug'),
    ]

    operations = [
        migrations.RunPython(gen_slug, reverse_code=migrations.RunPython.noop),
        # We set `reverse_code` to `noop` because we cannot revert the migration
        # to get it back in the previous state.
        # If `reverse_code` is not given, the migration will not be reversible,
        # which is not the behaviour we expect here.
    ]

Fausses migrations

Lorsqu'une migration est exécutée, Django stocke le nom de la migration dans une table django_migrations.

Créer et simuler des migrations initiales pour un schéma existant

Si votre application a déjà des modèles et des tables de base de données et ne dispose pas de migrations. Commencez par créer des migrations initiales pour votre application.

python manage.py makemigrations your_app_label

Faux migrations initiales maintenant appliquées

python manage.py migrate --fake-initial

Faux toutes les migrations dans toutes les applications

python manage.py migrate --fake

Fausses migrations d'applications uniques

python manage.py migrate --fake core

Faux fichier de migration unique

python manage.py migrate myapp migration_name

Noms personnalisés pour les fichiers de migration

Utilisez l' makemigrations --name <your_migration_name> pour autoriser la dénomination des migrations au lieu d'utiliser un nom généré.

python manage.py makemigrations --name <your_migration_name> <app_name>

Résoudre les conflits de migration

introduction

Parfois, les migrations sont en conflit, ce qui rend la migration infructueuse. Cela peut se produire dans de nombreux scénarios, mais cela peut se produire régulièrement lors du développement d'une application avec une équipe.

Les conflits de migration courants se produisent lors de l'utilisation du contrôle de source, en particulier lorsque la méthode de fonctionnalité par branche est utilisée. Pour ce scénario, nous utiliserons un modèle appelé Reporter avec le name et l' address attributs.

Deux développeurs à ce stade vont développer une fonctionnalité, ils obtiennent donc cette copie initiale du modèle Reporter . Le développeur A ajoute un age qui entraîne le fichier 0002_reporter_age.py . Le développeur B ajoute un champ bank_account qui 0002_reporter_bank_account . Une fois que ces développeurs fusionnent leur code et tentent de migrer les migrations, un conflit de migration s'est produit.

Ce conflit se produit car ces migrations modifient le même modèle, Reporter . De plus, les nouveaux fichiers commencent tous deux par 0002.

Fusion de migrations

Il y a plusieurs façons de le faire. Ce qui suit est dans l'ordre recommandé:

  1. La solution la plus simple consiste à exécuter la commande makemigrations avec un indicateur --merge.

    python manage.py makemigrations --merge <my_app>
    

    Cela créera une nouvelle migration pour résoudre le conflit précédent.

  2. Lorsque ce fichier supplémentaire n'est pas le bienvenu dans l'environnement de développement pour des raisons personnelles, vous pouvez supprimer les migrations en conflit. Ensuite, une nouvelle migration peut être effectuée à l'aide de la commande makemigrations . Lorsque des migrations personnalisées sont écrites, telles que migrations.RunPython , vous devez tenir compte de cette méthode.

Changer un CharField en un ForeignKey

Tout d'abord, supposons qu'il s'agisse de votre modèle initial, à l'intérieur d'une application appelée discography :

from django.db import models

class Album(models.Model):
    name = models.CharField(max_length=255)
    artist = models.CharField(max_length=255)

Maintenant, vous vous rendez compte que vous voulez utiliser un ForeignKey pour l'artiste à la place. C'est un processus assez complexe, qui doit être fait en plusieurs étapes.

Étape 1, ajoutez un nouveau champ pour ForeignKey, en veillant à le marquer comme nul (notez que le modèle auquel nous sommes liés est également maintenant inclus):

from django.db import models

class Album(models.Model):
    name = models.CharField(max_length=255)
    artist = models.CharField(max_length=255)
    artist_link = models.ForeignKey('Artist', null=True)

class Artist(models.Model):
    name = models.CharField(max_length=255)

... et créer une migration pour ce changement.

./manage.py makemigrations discography

Étape 2, remplissez votre nouveau champ. Pour ce faire, vous devez créer une migration vide.

./manage.py makemigrations --empty --name transfer_artists discography

Une fois que vous avez cette migration vide, vous souhaitez y ajouter une seule opération RunPython afin de lier vos enregistrements. Dans ce cas, cela pourrait ressembler à ceci:

def link_artists(apps, schema_editor):
    Album = apps.get_model('discography', 'Album')
    Artist = apps.get_model('discography', 'Artist')
    for album in Album.objects.all():
        artist, created = Artist.objects.get_or_create(name=album.artist)
        album.artist_link = artist
        album.save()

Maintenant que vos données sont transférées dans le nouveau champ, vous pouvez réellement le faire et tout laisser tel artist_link , en utilisant le nouveau champ artist_link pour tout. Ou, si vous souhaitez effectuer un peu de nettoyage, vous souhaitez créer deux autres migrations.

Pour votre première migration, vous souhaitez supprimer votre champ d'origine, artist . Pour votre deuxième migration, renommez le nouveau champ artist_link en artist .

Cela se fait en plusieurs étapes pour s'assurer que Django reconnaît correctement les opérations.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow