Szukaj…


Parametry

polecenie django-admin Detale
makemigrations <my_app> Generuj migracje dla my_app
makemigrations Generuj migracje dla wszystkich aplikacji
makemigrations --merge Rozwiąż konflikty migracyjne dla wszystkich aplikacji
makemigrations --merge <my_app> Rozwiąż konflikty migracyjne dla my_app
makemigrations --name <migration_name> <my_app> Generowanie migracji dla my_app pod nazwą migration_name
migrate <my_app> Zastosuj oczekujące migracje my_app do bazy danych
migrate Zastosuj wszystkie oczekujące migracje do bazy danych
migrate <my_app> <migration_name> Zastosuj lub usuń do migration_name
migrate <my_app> zero Anuluj wszystkie migracje w my_app
sqlmigrate <my_app> <migration_name> Wyświetla kod SQL dla nazwanej migracji
showmigrations Pokazuje wszystkie migracje dla wszystkich aplikacji
showmigrations <my_app> Pokazuje wszystkie migracje w my_app

Praca z migracjami

Django używa migracji do propagowania zmian wprowadzanych w modelach do bazy danych. Przez większość czasu django może je dla Ciebie wygenerować.

Aby utworzyć migrację, uruchom:

$ django-admin makemigrations <app_name>

Spowoduje to utworzenie pliku migracji w migration modułem z app_name . Pierwsza migracja będzie nosić nazwę 0001_initial.py , druga rozpocznie się od 0002_ , a następnie 0003 , ...

Pominięcie <app_name> spowoduje utworzenie migracji dla wszystkich INSTALLED_APPS .

Aby propagować migracje do bazy danych, uruchom:

$ django-admin migrate <app_name>

Aby wyświetlić wszystkie migracje, uruchom:

$ django-admin showmigrations app_name
app_name
  [X] 0001_initial
  [X] 0002_auto_20160115_1027
  [X] 0003_somemodel
  [ ] 0004_auto_20160323_1826
  • [X] oznacza, że migracja została propagowana do Twojej bazy danych
  • [ ] oznacza, że migracja nie została propagowana do Twojej bazy danych. Aby go propagować, użyj narzędzia django-admin migrate

Wywołujesz także przywracanie migracji, można to zrobić, przekazując nazwę migracji do migrate command . Biorąc pod uwagę powyższą listę migracji (pokazaną przez 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

Ręczne migracje

Czasami migracje generowane przez Django nie są wystarczające. Jest to szczególnie ważne, gdy chcesz przeprowadzić migrację danych .

Na przykład, niech masz taki model:

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

Ten model ma już istniejące dane, a teraz chcesz dodać SlugField :

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

Utworzyłeś migracje, aby dodać pole, ale teraz chcesz ustawić ślimak dla wszystkich istniejących artykułów, zgodnie z ich title .

Oczywiście możesz po prostu zrobić coś takiego w terminalu:

$ 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()
...
>>>

Ale będziesz musiał to zrobić we wszystkich swoich środowiskach (tj. Na biurowym pulpicie, twoim laptopie, ...), wszyscy twoi współpracownicy również będą musieli to zrobić, i będziesz musiał pomyśleć o tym podczas wystawiania i pchania relacja na żywo.

Aby to zrobić raz na zawsze, zrobimy to podczas migracji. Najpierw utwórz pustą migrację:

$ django-admin makemigrations --empty app_name

Spowoduje to utworzenie pustego pliku migracji. Otwórz, zawiera podstawowy szkielet. Załóżmy, że Twoja poprzednia migracja nosiła nazwę 0023_article_slug a ta nosi nazwę 0024_auto_20160719_1734 . Oto, co napiszemy w naszym pliku migracji:

# -*- 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.
    ]

Fałszywe migracje

Po uruchomieniu migracji Django przechowuje nazwę migracji w tabeli django_migrations.

Twórz i fałszuj początkowe migracje dla istniejącego schematu

Jeśli Twoja aplikacja ma już modele i tabele bazy danych i nie ma migracji. Najpierw utwórz początkowe migracje dla swojej aplikacji.

python manage.py makemigrations your_app_label

Teraz zastosuj fałszywe migracje początkowe

python manage.py migrate --fake-initial

Fałszywe wszystkie migracje we wszystkich aplikacjach

python manage.py migrate --fake

Fałszywe migracje pojedynczych aplikacji

python manage.py migrate --fake core

Fałszywy pojedynczy plik migracji

python manage.py migrate myapp migration_name

Niestandardowe nazwy plików migracji

Użyj opcji makemigrations --name <your_migration_name> , aby zezwolić na nazwanie migracji zamiast używania wygenerowanej nazwy.

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

Rozwiązywanie konfliktów migracyjnych

Wprowadzenie

Czasami migracje powodują konflikty, co powoduje, że migracja kończy się niepowodzeniem. Może się to zdarzyć w wielu sceneriach, jednak może się zdarzyć regularnie podczas opracowywania jednej aplikacji z zespołem.

Typowe konflikty migracyjne zdarzają się podczas korzystania z kontroli źródła, szczególnie gdy używana jest metoda funkcja dla gałęzi. W tym scenariuszu użyjemy modelu o nazwie Reporter z name i address atrybutu.

Dwóch programistów w tym momencie zamierza opracować funkcję, dlatego oboje otrzymują tę początkową kopię modelu Reporter . Deweloper A dodaje age co powoduje utworzenie pliku 0002_reporter_age.py . Deweloper B dodaje pole bank_account które 0002_reporter_bank_account w 0002_reporter_bank_account . Gdy ci programiści scalą razem swój kod i spróbują przeprowadzić migrację, wystąpił konflikt migracyjny.

Ten konflikt występuje, ponieważ obie migracje zmieniają ten sam model Reporter . Ponadto oba nowe pliki zaczynają się od 0002.

Scalanie migracji

Można to zrobić na kilka sposobów. Poniższa kolejność jest zalecana:

  1. Najprostszym rozwiązaniem tego problemu jest uruchomienie polecenia makemigrations z flagą --merge.

    python manage.py makemigrations --merge <my_app>
    

    Spowoduje to utworzenie nowej migracji rozwiązującej poprzedni konflikt.

  2. Jeśli ten dodatkowy plik nie jest mile widziany w środowisku programistycznym z powodów osobistych, można usunąć migracje powodujące konflikt. Następnie można przeprowadzić nową migrację za pomocą zwykłego polecenia makemigrations . Podczas pisania niestandardowych migracji, takich jak migrations.RunPython , należy uwzględnić tę metodę.

Zmień CharField na ForeignKey

Po pierwsze, załóżmy, że to twój początkowy model w aplikacji o nazwie discography :

from django.db import models

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

Teraz zdajesz sobie sprawę, że zamiast tego chcesz użyć klucza zagranicznego dla artysty. Jest to dość złożony proces, który należy wykonać w kilku etapach.

Krok 1, dodaj nowe pole dla klucza ForeignKey, upewniając się, że oznaczono je jako null (zwróć uwagę, że model, z którym się łączymy, jest teraz dołączony):

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)

... i utwórz migrację dla tej zmiany.

./manage.py makemigrations discography

Krok 2, wypełnij nowe pole. Aby to zrobić, musisz utworzyć pustą migrację.

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

Po zakończeniu tej pustej migracji chcesz dodać do niej pojedynczą operację RunPython , aby połączyć swoje rekordy. W takim przypadku może wyglądać mniej więcej tak:

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()

Teraz, gdy Twoje dane są przenoszone do nowego pola, możesz faktycznie zrobić i pozostawić wszystko bez artist_link , używając nowego pola artist_link do wszystkiego. Lub, jeśli chcesz zrobić trochę czyszczenia, chcesz utworzyć dwie kolejne migracje.

Podczas pierwszej migracji będziesz chciał usunąć swoje oryginalne pole, artist . Podczas drugiej migracji zmień nazwę nowego pola artist_link na artist .

Odbywa się to w kilku krokach, aby zapewnić prawidłowe rozpoznanie operacji przez Django.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow