Sök…


parametrar

django-admin kommando detaljer
makemigrations <my_app> Generera migreringar för my_app
makemigrations Generera migreringar för alla appar
makemigrations --merge Lös migrationskonflikter för alla appar
makemigrations --merge <my_app> Lös migrationskonflikter för my_app
makemigrations --name <migration_name> <my_app> Generera en migrering för my_app med namnet migration_name
migrate <my_app> Tillämpa väntande migreringar av my_app i databasen
migrate Använd alla väntande migrationer i databasen
migrate <my_app> <migration_name> Använd eller avaktivera upp till migration_name
migrate <my_app> zero Avlägsna alla migreringar i my_app
sqlmigrate <my_app> <migration_name> Skriver ut SQL för den namngivna migreringen
showmigrations Visar alla migreringar för alla appar
showmigrations <my_app> Visar alla migreringar i my_app

Arbeta med migrationer

Django använder migreringar för att sprida ändringar du gör i dina modeller till din databas. Django kan oftast generera dem åt dig.

För att skapa en migrering, kör:

$ django-admin makemigrations <app_name>

Detta skapar en migreringsfil i migration för app_name . Den första migrationen kommer att kallas 0001_initial.py , den andra kommer att börja med 0002_ , sedan 0003 , ...

Om du utelämnar <app_name> skapar det migreringar för alla dina INSTALLED_APPS .

För att sprida migreringar till din databas, kör:

$ django-admin migrate <app_name>

För att visa alla dina migrationer, kör:

$ django-admin showmigrations app_name
app_name
  [X] 0001_initial
  [X] 0002_auto_20160115_1027
  [X] 0003_somemodel
  [ ] 0004_auto_20160323_1826
  • [X] betyder att migreringen spridits till din databas
  • [ ] betyder att migreringen inte spridits till din databas. Använd django-admin migrate att sprida den

Du ringer också omvandla migrationer, detta kan göras genom att överföra migreringsnamnet till migrate command . Med tanke på ovanstående lista över migrationer (visas av 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

Manuella migreringar

Ibland är migrationer som genereras av Django inte tillräckliga. Detta gäller särskilt när du vill göra datamigreringar .

Låt oss till exempel ha en sådan modell:

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

Den här modellen har redan befintliga data och nu vill du lägga till ett SlugField :

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

Du skapade migreringarna för att lägga till fältet, men nu vill du ställa in snigeln för alla befintliga artiklar, enligt deras title .

Naturligtvis kan du bara göra något liknande i terminalen:

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

Men du måste göra detta i alla dina miljöer (dvs. ditt skrivbord, din bärbara dator, ...), alla dina medarbetare måste göra det också, och du kommer att behöva tänka på det på scenen och när du trycker leva.

För att göra det en gång för alla, kommer vi att göra det i en migration. Skapa först en tom migrering:

$ django-admin makemigrations --empty app_name

Detta skapar en tom migreringsfil. Öppna den, den innehåller ett basskelett. Låt oss säga att din tidigare migrering hette 0023_article_slug och den här heter 0024_auto_20160719_1734 . Så här skriver vi i vår migreringsfil:

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

Falska migrationer

När en migrering körs lagrar Django namnet på migreringen i en django_migrations-tabell.

Skapa och förfalska initiala migreringar för befintligt schema

Om din app redan har modeller och databastabeller och inte har migreringar. Skapa först initiala migreringar för din app.

python manage.py makemigrations your_app_label

Nu falska initiala migrationer som tillämpats

python manage.py migrate --fake-initial

Fake all migration i alla appar

python manage.py migrate --fake

Fake enstaka app migrationer

python manage.py migrate --fake core

Fake enda migreringsfil

python manage.py migrate myapp migration_name

Anpassade namn för migreringsfiler

Använd makemigrations --name <your_migration_name> att tillåta namnge migreringarna i stället för att använda ett genererat namn.

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

Lösa migrationskonflikter

Introduktion

Ibland konflikter migrationer, vilket resulterar i att migrationen är osuccesfull. Detta kan hända i många scenerier, men det kan uppstå regelbundet när man utvecklar en app med ett team.

Vanliga migrationskonflikter inträffar när man använder källkontroll, särskilt när metoden per filial används. För det här scenariot kommer vi att använda en modell som heter Reporter med attributens name och address .

Två utvecklare vid denna tidpunkt kommer att utveckla en funktion, varför de båda får den här första kopian av Reporter modellen. Utvecklare A lägger till en age som resulterar i filen 0002_reporter_age.py filen. Developer B ger en bank_account fält som resulsts i 0002_reporter_bank_account . När dessa utvecklare smälter samman sin kod och försökte migrera migreringarna inträffade en migrationskonflikt.

Denna konflikt inträffar eftersom dessa migrationer båda förändrar samma modell, Reporter . Dessutom börjar de nya filerna båda med 0002.

Slå samman migreringar

Det finns flera sätt att göra det på. Följande är i den rekommenderade ordningen:

  1. Den enklaste fixen för detta är genom att köra kommandot makemigrations med en - flagg.

    python manage.py makemigrations --merge <my_app>
    

    Detta skapar en ny migrering som löser den tidigare konflikten.

  2. När denna extra fil av personliga skäl inte är välkommen i utvecklingsmiljön, är ett alternativ att ta bort de motstridiga migrationerna. Sedan kan en ny migrering göras med kommandot vanliga makemigrations . När anpassade migrationer skrivs, till exempel migrations.RunPython , måste redovisas för att använda den här metoden.

Byt ett CharField till ett ForeignKey

Först och främst, låt oss anta att detta är din ursprungliga modell, i en applikation som kallas discography :

from django.db import models

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

Nu inser du att du istället vill använda ett ForeignKey för artisten. Detta är en något komplex process som måste göras i flera steg.

Steg 1, lägg till ett nytt fält för ForeignKey och se till att markera det som null (Observera att modellen vi länkar till också nu ingår):

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)

... och skapa en migrering för den här förändringen.

./manage.py makemigrations discography

Steg 2, fyll i ditt nya fält. För att göra detta måste du skapa en tom migrering.

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

När du har tagit den tomma migreringen vill du lägga till en enda RunPython operation till den för att länka dina poster. I det här fallet kan det se ut så här:

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

Nu när dina data överförs till det nya fältet kan du faktiskt göra det och lämna allt som det är, med det nya artist_link fältet för allt. Eller, om du vill göra en del sanering, vill du skapa ytterligare två migrationer.

För din första migrering vill du ta bort ditt ursprungliga fält, artist . För din andra migrering, byta namn på det nya fältet artist_link till artist .

Detta görs i flera steg för att säkerställa att Django känner igen operationerna korrekt.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow