Zoeken…


parameters

django-admin commando Details
makemigrations <my_app> Genereer migraties voor my_app
makemigrations Genereer migraties voor alle apps
makemigrations --merge Los migratieconflicten op voor alle apps
makemigrations --merge <my_app> Migratieconflicten voor my_app
makemigrations --name <migration_name> <my_app> Genereer een migratie voor my_app met de naam migration_name
migrate <my_app> Pas lopende migraties van my_app op de database
migrate Pas alle uitstaande migraties toe op de database
migrate <my_app> <migration_name> Toepassen of niet meer toepassen op migration_name
migrate <my_app> zero Alle migraties in my_app
sqlmigrate <my_app> <migration_name> Hiermee wordt de SQL voor de genoemde migratie afgedrukt
showmigrations Toont alle migraties voor alle apps
showmigrations <my_app> Toont alle migraties in my_app

Werken met migraties

Django gebruikt migraties om wijzigingen die u aanbrengt in uw modellen door te geven aan uw database. Meestal kan django ze voor u genereren.

Voer het volgende uit om een migratie te maken:

$ django-admin makemigrations <app_name>

Hiermee wordt een migratiebestand gemaakt in de migration submodule van app_name . De eerste migratie krijgt de naam 0001_initial.py , de andere begint met 0002_ , daarna 0003 , ...

Als u <app_name> dit migraties voor al uw INSTALLED_APPS .

Voer de volgende stappen uit om migraties naar uw database door te geven:

$ django-admin migrate <app_name>

Voer het volgende uit om al uw migraties te tonen:

$ django-admin showmigrations app_name
app_name
  [X] 0001_initial
  [X] 0002_auto_20160115_1027
  [X] 0003_somemodel
  [ ] 0004_auto_20160323_1826
  • [X] betekent dat de migratie is doorgegeven aan uw database
  • [ ] betekent dat de migratie niet is doorgegeven aan uw database. Gebruik django-admin migrate om het te verspreiden

U roept ook migraties terug, dit kunt u doen door de migratienaam door te geven aan de migrate command . Gezien de bovenstaande lijst met migraties (getoond door 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

Handmatige migraties

Soms zijn migraties gegenereerd door Django niet voldoende. Dit geldt met name als u gegevensmigraties wilt maken.

Laten we bijvoorbeeld een dergelijk model hebben:

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

Dit model heeft al bestaande gegevens en nu wilt u een SlugField :

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

U hebt de migraties gemaakt om het veld toe te voegen, maar nu wilt u de slak instellen voor alle bestaande artikelen, op basis van hun title .

Natuurlijk kun je zoiets in de terminal gewoon doen:

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

Maar je zult dit in al je omgevingen moeten doen (bijv. Je desktop op kantoor, je laptop, ...), al je collega's zullen dit ook moeten doen, en je moet erover nadenken bij het ensceneren en bij het pushen leven.

Om het voor eens en altijd te maken, doen we het in een migratie. Maak eerst een lege migratie:

$ django-admin makemigrations --empty app_name

Hiermee maakt u een leeg migratiebestand. Open het, het bevat een basisskelet. Stel dat uw vorige migratie de naam 0023_article_slug en deze heeft de naam 0024_auto_20160719_1734 . Hier is wat we zullen schrijven in ons migratiebestand:

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

Valse migraties

Wanneer een migratie wordt uitgevoerd, slaat Django de naam van de migratie op in een tabel django_migrations.

Maak en valse initiële migraties voor een bestaand schema

Als uw app al modellen en databasetabellen heeft en geen migraties heeft. Maak eerst de initiële migraties voor uw app.

python manage.py makemigrations your_app_label

Nu nep initiële migraties zoals toegepast

python manage.py migrate --fake-initial

Nep alle migraties in alle apps

python manage.py migrate --fake

Valse single app-migraties

python manage.py migrate --fake core

Nep nep migratiebestand

python manage.py migrate myapp migration_name

Aangepaste namen voor migratiebestanden

Gebruik de optie makemigrations --name <your_migration_name> om de migratie (s) een naam te geven in plaats van een gegenereerde naam te gebruiken.

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

Migratieconflicten oplossen

Invoering

Soms conflicteren migraties, waardoor de migratie mislukt. Dit kan in veel scenario's gebeuren, maar het kan regelmatig voorkomen bij het ontwikkelen van een app met een team.

Veelvoorkomende migratieconflicten treden op tijdens het gebruik van bronbeheer, vooral wanneer de methode feature-per-branch wordt gebruikt. Voor dit scenario gebruiken we een model met de name Reporter met de attributen name en address .

Twee ontwikkelaars gaan op dit moment een functie ontwikkelen, dus krijgen ze allebei dit eerste exemplaar van het Reporter model. Ontwikkelaar A voegt een age die resulteert in het bestand 0002_reporter_age.py . Developer B voegt een bank_account veld dat resulsts in 0002_reporter_bank_account . Zodra deze ontwikkelaars hun code samenvoegen en proberen de migraties te migreren, trad een migratieconflict op.

Dit conflict treedt op omdat beide migraties hetzelfde model, Reporter . Bovendien beginnen de nieuwe bestanden beide met 0002.

Migraties samenvoegen

Er zijn verschillende manieren om dit te doen. Het volgende is in de aanbevolen volgorde:

  1. De meest eenvoudige oplossing hiervoor is door de opdracht makemigrations uit te voeren met een vlag --merge.

    python manage.py makemigrations --merge <my_app>
    

    Dit zal een nieuwe migratie creëren die het vorige conflict oplost.

  2. Wanneer dit extra bestand om persoonlijke redenen niet welkom is in de ontwikkelomgeving, is een optie om de conflicterende migraties te verwijderen. Vervolgens kan een nieuwe migratie worden gemaakt met behulp van de reguliere opdracht makemigrations . Wanneer aangepaste migraties worden geschreven, zoals migrations.RunPython . migrations.RunPython , moet met deze methode worden verantwoord.

Verander een CharField in een ForeignKey

Laten we eerst aannemen dat dit uw eerste model is, binnen een applicatie genaamd discography :

from django.db import models

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

Nu realiseer je je dat je in plaats daarvan een ForeignKey voor de artiest wilt gebruiken. Dit is een ietwat complex proces, dat in verschillende stappen moet worden uitgevoerd.

Stap 1, voeg een nieuw veld toe voor de ForeignKey en zorg ervoor dat het als nul wordt gemarkeerd (merk op dat het model waarnaar we linken nu ook is opgenomen):

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)

... en maak een migratie voor deze wijziging.

./manage.py makemigrations discography

Stap 2, vul uw nieuwe veld in. Om dit te doen, moet u een lege migratie maken.

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

Zodra u deze lege migratie heeft, wilt u er een enkele RunPython bewerking aan toevoegen om uw records te koppelen. In dit geval kan het er ongeveer zo uitzien:

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 uw gegevens naar het nieuwe veld zijn overgebracht, kunt u eigenlijk alles doen en alles laten zoals het is, met het nieuwe veld artist_link voor alles. Of, als u een beetje wilt opschonen, wilt u nog twee migraties maken.

Voor uw eerste migratie wilt u uw oorspronkelijke veld, artist . artist_link voor uw tweede migratie het nieuwe veld artist_link naar artist .

Dit gebeurt in meerdere stappen om ervoor te zorgen dat Django de bewerkingen correct herkent.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow