Django
Migrationen
Suche…
Parameter
django-admin befehl | Einzelheiten |
---|---|
makemigrations <my_app> | Generieren Sie Migrationen für my_app |
makemigrations | Generieren Sie Migrationen für alle Apps |
makemigrations --merge | Lösen Sie Migrationskonflikte für alle Apps |
makemigrations --merge <my_app> | Migrationskonflikte für my_app |
makemigrations --name <migration_name> <my_app> | Generieren Sie eine Migration für my_app mit dem Namen migration_name |
migrate <my_app> | Wenden Sie ausstehende Migrationen von my_app auf die Datenbank an |
migrate | Wenden Sie alle ausstehenden Migrationen auf die Datenbank an |
migrate <my_app> <migration_name> | Auf migration_name anwenden oder nicht zutreffend |
migrate <my_app> zero | Nicht zutreffend alle Migrationen in my_app |
sqlmigrate <my_app> <migration_name> | Gibt die SQL für die genannte Migration aus |
showmigrations | Zeigt alle Migrationen für alle Apps an |
showmigrations <my_app> | Zeigt alle Migrationen in my_app |
Mit Migrationen arbeiten
Django verwendet Migrationen, um Änderungen, die Sie an Ihren Modellen vornehmen, in Ihre Datenbank zu übernehmen. Die meiste Zeit kann Django sie für Sie erzeugen.
Führen Sie zum Erstellen einer Migration Folgendes aus:
$ django-admin makemigrations <app_name>
Dadurch wird eine Migrationsdatei im migration
von app_name
. Die erste Migration wird 0001_initial.py
, die andere beginnt mit 0002_
, dann 0003
, ...
Wenn Sie <app_name>
weglassen, werden Migrationen für alle Ihre INSTALLED_APPS
.
Führen Sie zum Weiterleiten von Migrationen in Ihre Datenbank Folgendes aus:
$ django-admin migrate <app_name>
Führen Sie Folgendes aus, um alle Migrationen anzuzeigen:
$ django-admin showmigrations app_name
app_name
[X] 0001_initial
[X] 0002_auto_20160115_1027
[X] 0003_somemodel
[ ] 0004_auto_20160323_1826
-
[X]
bedeutet, dass die Migration in Ihre Datenbank übernommen wurde -
[ ]
bedeutet, dass die Migration nicht in Ihre Datenbank übernommen wurde. Verwenden Siedjango-admin migrate
, um es zu verbreiten
Sie rufen auch Migrationen auf, indem Sie den Migrationsnamen an den migrate command
. In Anbetracht der obigen Migrationsliste (angezeigt durch 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
Manuelle Migrationen
Manchmal reichen von Django erzeugte Migrationen nicht aus. Dies gilt insbesondere, wenn Sie Datenmigrationen durchführen möchten.
Zum Beispiel haben wir ein solches Modell:
class Article(models.Model):
title = models.CharField(max_length=70)
Dieses Modell hat bereits Daten, und Sie möchten nun ein SlugField
hinzufügen:
class Article(models.Model):
title = models.CharField(max_length=70)
slug = models.SlugField(max_length=70)
Sie haben die Migrationen erstellt, um das Feld hinzuzufügen. Jetzt möchten Sie den Slug für alle vorhandenen Artikel entsprechend ihrem title
festlegen.
Natürlich können Sie im Terminal so etwas tun:
$ 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()
...
>>>
Sie müssen dies jedoch in all Ihren Umgebungen tun (z. B. Ihrem Bürodesktop, Ihrem Laptop, ...), alle Ihre Kollegen müssen dies ebenfalls tun, und Sie müssen bei der Inszenierung und beim Push darüber nachdenken Leben.
Um es ein für alle Mal zu schaffen, machen wir es in einer Migration. Erstellen Sie zuerst eine leere Migration:
$ django-admin makemigrations --empty app_name
Dadurch wird eine leere Migrationsdatei erstellt. Öffnen Sie es, es enthält ein Grundgerüst. Nehmen wir an, Ihre vorherige Migration hatte den Namen 0023_article_slug
und dieser heißt 0024_auto_20160719_1734
. Folgendes schreiben wir in unsere Migrationsdatei:
# -*- 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.
]
Gefälschte Migrationen
Wenn eine Migration ausgeführt wird, speichert Django den Namen der Migration in einer Tabelle django_migrations.
Erstellen und fälschen Sie anfängliche Migrationen für ein vorhandenes Schema
Wenn Ihre App bereits über Modelle und Datenbanktabellen verfügt und keine Migrationen vorhanden sind. Erstellen Sie zunächst erste Migrationen für Ihre App.
python manage.py makemigrations your_app_label
Nun fälschen Sie anfängliche Migrationen, wie sie angewendet werden
python manage.py migrate --fake-initial
Fake alle Migrationen in allen Apps
python manage.py migrate --fake
Gefälschte Migrationen einzelner Apps
python manage.py migrate --fake core
Gefälschte einzelne Migrationsdatei
python manage.py migrate myapp migration_name
Benutzerdefinierte Namen für Migrationsdateien
Verwenden Sie die Option makemigrations --name <your_migration_name>
, um die Benennung der Migrationen zu erlauben, anstatt einen generierten Namen zu verwenden.
python manage.py makemigrations --name <your_migration_name> <app_name>
Migrationskonflikte lösen
Einführung
Migrationen führen manchmal zu Konflikten, was dazu führt, dass die Migration nicht erfolgreich ist. Dies kann in vielen Szenarien der Fall sein, kann jedoch regelmäßig auftreten, wenn eine App mit einem Team entwickelt wird.
Häufige Migrationskonflikte treten bei der Verwendung der Quellcodeverwaltung auf, insbesondere wenn die Feature-pro-Branch-Methode verwendet wird. Für dieses Szenario werden wir ein Modell namens verwenden Reporter
mit den Attributen name
und address
.
Zu diesem Zeitpunkt werden zwei Entwickler eine Funktion entwickeln, daher erhalten beide diese erste Kopie des Reporter
Modells. Entwickler A fügt ein age
das in der Datei 0002_reporter_age.py
. Entwickler B fügt ein bank_account
Feld hinzu, das in 0002_reporter_bank_account 0002_reporter_bank_account
. Sobald diese Entwickler ihren Code zusammenführen und versuchen, die Migrationen zu migrieren, ist ein Migrationskonflikt aufgetreten.
Dieser Konflikt tritt auf, weil diese Migrationen dasselbe Modell, Reporter
ändern. Darüber hinaus beginnen die neuen Dateien beide mit 0002.
Migrationen zusammenführen
Es gibt verschiedene Möglichkeiten, dies zu tun. Folgendes ist in der empfohlenen Reihenfolge:
Die einfachste Lösung für dieses Problem besteht darin, den Befehl makemigrations mit einem Flag --merge auszuführen.
python manage.py makemigrations --merge <my_app>
Dadurch wird eine neue Migration erstellt, die den vorherigen Konflikt löst.
Wenn diese zusätzliche Datei aus persönlichen Gründen in der Entwicklungsumgebung nicht erwünscht ist, können Sie die in Konflikt stehenden Migrationen löschen. Dann kann eine neue Migration mit dem regulären Befehl
makemigrations
. Wenn benutzerdefinierte Migrationen geschrieben werden, wie z. B.migrations.RunPython
, müssen Sie diese Methode verwenden.
Ändern Sie ein CharField in einen ForeignKey
Nehmen wir zunächst einmal an, dies ist Ihr Ausgangsmodell in einer Anwendung namens discography
:
from django.db import models
class Album(models.Model):
name = models.CharField(max_length=255)
artist = models.CharField(max_length=255)
Jetzt erkennen Sie, dass Sie stattdessen einen ForeignKey für den Interpreten verwenden möchten. Dies ist ein etwas komplexer Prozess, der in mehreren Schritten erfolgen muss.
Fügen Sie in Schritt 1 ein neues Feld für den ForeignKey hinzu, und stellen Sie sicher, dass es als null markiert ist.
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)
... und erstellen Sie eine Migration für diese Änderung.
./manage.py makemigrations discography
Schritt 2, füllen Sie Ihr neues Feld aus. Dazu müssen Sie eine leere Migration erstellen.
./manage.py makemigrations --empty --name transfer_artists discography
Nachdem Sie diese leere Migration durchgeführt haben, möchten Sie eine einzelne RunPython
Operation hinzufügen, um Ihre Datensätze zu verknüpfen. In diesem Fall könnte es ungefähr so aussehen:
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()
Jetzt, da Ihre Daten in das neue Feld übertragen werden, können Sie tatsächlich alles erledigen, indem Sie das neue Feld artist_link
für alles verwenden. Wenn Sie eine Bereinigung durchführen möchten, möchten Sie zwei weitere Migrationen erstellen.
Für Ihre erste Migration sollten Sie Ihr ursprüngliches Feld, artist
, löschen. artist_link
für Ihre zweite Migration das neue Feld artist_link
in artist
.
Dies geschieht in mehreren Schritten, um sicherzustellen, dass Django die Vorgänge richtig erkennt.