MigrationsverksamhetLink to this heading

Migreringsfiler består av en eller flera ”Operation”-objekt, objekt som deklarativt registrerar vad migreringen ska göra med din databas.

Django använder också dessa Operation-objekt för att räkna ut hur dina modeller såg ut historiskt och för att beräkna vilka ändringar du har gjort i dina modeller sedan den senaste migreringen så att den automatiskt kan skriva dina migreringar; det är därför de är deklarativa, eftersom det betyder att Django enkelt kan ladda dem alla i minnet och köra igenom dem utan att röra databasen för att räkna ut hur ditt projekt ska se ut.

Det finns också mer specialiserade Operation-objekt som är till för saker som datamigreringar och för avancerad manuell databasmanipulation. Du kan också skriva dina egna Operation-klasser om du vill kapsla in en anpassad förändring som du ofta gör.

Om du behöver en tom migreringsfil för att skriva in dina egna Operation-objekt i, använd python manage.py makemigrations --empty yourappname, men tänk på att manuellt tillägg av schemaändrande operationer kan förvirra migreringsautodetektorn och göra att resulterande körningar av makemigrations ger felaktig kod.

Alla Django-kärnoperationer är tillgängliga från modulen django.db.migrations.operations.

För introduktionsmaterial, se migrations topic guide.

Schema-verksamhetLink to this heading

SkapaModellLink to this heading

class CreateModel(name, fields, options=None, bases=None, managers=None)Link to this definition

Skapar en ny modell i projekthistoriken och en motsvarande tabell i databasen för att matcha den.

name är modellnamnet, som det skulle skrivas i filen models.py.

fields är en lista med 2-tuples av (field_name, field_instance). Fältinstansen ska vara ett obundet fält (så bara models.CharField(...), snarare än ett fält som hämtats från en annan modell).

options är en valfri ordlista med värden från modellens Meta-klass.

bases är en valfri lista över andra klasser som den här modellen ska ärva från; den kan innehålla både klassobjekt och strängar i formatet "appname.ModelName" om du vill vara beroende av en annan modell (så att du ärver från den historiska versionen). Om den inte anges ärver den som standard från standardmodellen models.Model.

managers tar en lista med 2-tuples av (manager_name, manager_instance). Den första hanteraren i listan kommer att vara standardhanteraren för den här modellen under migreringar.

DeleteModelLink to this heading

class DeleteModel(name)Link to this definition

Raderar modellen från projekthistoriken och dess tabell från databasen.

RenameModelLink to this heading

class RenameModel(old_name, new_name)Link to this definition

Byter namn på modellen från ett gammalt namn till ett nytt.

Du kan behöva lägga till detta manuellt om du ändrar modellens namn och en hel del av dess fält på en gång. För autodetektorn ser det ut som om du har tagit bort en modell med det gamla namnet och lagt till en ny med ett annat namn, och den migrering som skapas kommer att förlora alla data i den gamla tabellen.

AlterModelTableLink to this heading

class AlterModelTable(name, table)Link to this definition

Ändrar modellens tabellnamn (alternativet db_table på underklassen Meta).

AlterModelTableKommentarLink to this heading

class AlterModelTableComment(name, table_comment)Link to this definition

Ändrar modellens tabellkommentar (alternativet db_table_comment på underklassen Meta).

AlterUniqueTogetherLink to this heading

class AlterUniqueTogether(name, unique_together)Link to this definition

Ändrar modellens uppsättning av unika begränsningar (alternativet unique_together på underklassen Meta).

AlterIndexTillsammanLink to this heading

class AlterIndexTogether(name, index_together)Link to this definition

Ändrar modellens uppsättning av anpassade index (alternativet index_together i underklassen Meta).

AlterOrderMedAvseendePåLink to this heading

class AlterOrderWithRespectTo(name, order_with_respect_to)Link to this definition

Skapar eller tar bort kolumnen _order som behövs för alternativet order_with_respect_to på subklassen Meta.

AlterModelOptionsLink to this heading

class AlterModelOptions(name, options)Link to this definition

Lagrar ändringar av olika modellalternativ (inställningar på en modells Meta) som permissions och verbose_name. Påverkar inte databasen, men lagrar dessa ändringar så att RunPython-instanser kan använda dem. options bör vara en ordbok som mappar alternativnamn till värden.

AlterModelManagersLink to this heading

class AlterModelManagers(name, managers)Link to this definition

Ändrar de chefer som är tillgängliga under migreringar.

AddFieldLink to this heading

class AddField(model_name, name, field, preserve_default=True)Link to this definition

Lägger till ett fält till en modell. model_name är modellens namn, name är fältets namn och field är en obunden fältinstans (det som du skulle lägga till i fältdeklarationen i models.py - till exempel models.IntegerField(null=True).

The preserve_default argument indicates whether the field’s default value is permanent and should be baked into the project state (True), or if it is temporary and just for this migration (False) - usually because the migration is adding a non-nullable field to a table and needs a default value to put into existing rows. It does not affect the behavior of setting defaults in the database directly.

Avlägsna fältLink to this heading

class RemoveField(model_name, name)Link to this definition

Tar bort ett fält från en modell.

Tänk på att detta faktiskt innebär att ett fält läggs till i en modell när det vänds. Åtgärden är reversibel (bortsett från eventuell dataförlust, som är irreversibel) om fältet är nollställbart eller om det har ett standardvärde som kan användas för att fylla i den återskapade kolumnen. Om fältet inte är nollställbart och inte har något standardvärde är åtgärden irreversibel.

AlterFieldLink to this heading

class AlterField(model_name, name, field, preserve_default=True)Link to this definition

Ändrar ett fälts definition, inklusive ändringar av dess typ, null, unique, db_column och andra fältattribut.

The preserve_default argument indicates whether the field’s default value is permanent and should be baked into the project state (True), or if it is temporary and just for this migration (False) - usually because the migration is altering a nullable field to a non-nullable one and needs a default value to put into existing rows. It does not affect the behavior of setting defaults in the database directly.

Observera att alla ändringar inte är möjliga i alla databaser - du kan t.ex. inte ändra ett fält av texttyp som models.TextField() till ett fält av siffertyp som models.IntegerField() i de flesta databaser.

RenameFieldLink to this heading

class RenameField(model_name, old_name, new_name)Link to this definition

Ändrar ett fälts namn (och, om inte db_column har angetts, dess kolumnnamn).

AddIndexLink to this heading

class AddIndex(model_name, index)Link to this definition

Skapar ett index i databastabellen för modellen med model_name. index är en instans av klassen Index.

RemoveIndexLink to this heading

class RemoveIndex(model_name, name)Link to this definition

Tar bort indexet med namnet name från modellen med model_name.

RenameIndexLink to this heading

class RenameIndex(model_name, new_name, old_name=None, old_fields=None)Link to this definition

Byter namn på ett index i databastabellen för modellen med model_name. Exakt ett av old_name och old_fields kan anges. old_fields är en iterabel av strängarna, som ofta motsvarar fält i index_together (alternativ före Django 5.1).

On databases that don’t support an index renaming statement (SQLite), the operation will drop and recreate the index, which can be expensive.

AddConstraintLink to this heading

class AddConstraint(model_name, constraint)Link to this definition

Skapar en constraint i databastabellen för modellen med model_name.

”Ta bort begränsningLink to this heading

class RemoveConstraint(model_name, name)Link to this definition

Tar bort begränsningen med namnet namn från modellen med modell_namn.

AlterConstraintLink to this heading

class AlterConstraint(model_name, name, constraint)Link to this definition

Ändrar begränsningen med namnet name i modellen med model_name med den nya constraint utan att påverka databasen.

SpecialoperationerLink to this heading

RunSQLLink to this heading

class RunSQL(sql, reverse_sql=None, state_operations=None, hints=None, elidable=False)Link to this definition

Gör det möjligt att köra godtycklig SQL på databasen - användbart för mer avancerade funktioner i databasbackends som Django inte stöder direkt.

sql, och reverse_sql om det tillhandahålls, bör vara strängar av SQL som ska köras på databasen. På de flesta databasbackends (alla utom PostgreSQL) kommer Django att dela upp SQL i enskilda uttalanden innan de körs.

Du kan också skicka en lista med strängar eller 2-tupler. Den senare används för att skicka frågor och parametrar på samma sätt som cursor.execute(). Dessa tre operationer är likvärdiga:

Code
migrations.RunSQL("INSERT INTO musician (name) VALUES ('Reinhardt');")
migrations.RunSQL([("INSERT INTO musician (name) VALUES ('Reinhardt');", None)])
migrations.RunSQL([("INSERT INTO musician (name) VALUES (%s);", ["Reinhardt"])])

Om du vill inkludera bokstavliga procenttecken i frågan måste du dubbla dem om du skickar parametrar.

Frågorna reverse_sql körs när migreringen inte tillämpas. De bör ångra det som gjorts av sql-frågorna. Till exempel:, för att ångra ovanstående infogning med en borttagning:

Code
migrations.RunSQL(
    sql=[("INSERT INTO musician (name) VALUES (%s);", ["Reinhardt"])],
    reverse_sql=[("DELETE FROM musician where name=%s;", ["Reinhardt"])],
)

Om reverse_sql är None (standard) är RunSQL-operationen irreversibel.

Med argumentet state_operations kan du ange operationer som är likvärdiga med SQL när det gäller projektstatus. Om du till exempel skapar en kolumn manuellt bör du skicka in en lista som innehåller en AddField operation här så att autodetektorn fortfarande har ett uppdaterat tillstånd för modellen. Om du inte gör det, när du nästa gång kör makemigrations, kommer den inte att se någon operation som lägger till det fältet och kommer därför att försöka köra den igen. Till exempel:

Code
migrations.RunSQL(
    "ALTER TABLE musician ADD COLUMN name varchar(255) NOT NULL;",
    state_operations=[
        migrations.AddField(
            "musician",
            "name",
            models.CharField(max_length=255),
        ),
    ],
)

Det valfria argumentet hints kommer att skickas som **hints till metoden allow_migrate`() i databasroutrar för att hjälpa dem att fatta beslut om routning. Se Tips för mer information om databastips.

Det valfria argumentet elidable avgör om åtgärden ska tas bort (elided) när squashing migrations.

RunSQL.noopLink to this definition

Skicka attributet RunSQL.noop till sql eller reverse_sql när du vill att operationen inte ska göra någonting i den angivna riktningen. Detta är särskilt användbart för att göra operationen reversibel.

RunPythonLink to this heading

class RunPython(code, reverse_code=None, atomic=None, hints=None, elidable=False)Link to this definition

Kör anpassad Python-kod i ett historiskt sammanhang. code (och reverse_code om det tillhandahålls) ska vara anropsbara objekt som accepterar två argument; det första är en instans av django.apps.registry.Apps som innehåller historiska modeller som matchar operationens plats i projekthistoriken, och det andra är en instans av SchemaEditor.

Argumentet reverse_code anropas vid avapplicering av migreringar. Denna anropbara bör ångra vad som gjorts i den anropbara code så att migreringen är reversibel. Om reverse_code är None (standard), är RunPython-operationen irreversibel.

Det valfria argumentet hints kommer att skickas som **hints till metoden allow_migrate`() i databasroutrar för att hjälpa dem att fatta ett routningsbeslut. Se Tips för mer information om databastips.

Det valfria argumentet elidable avgör om åtgärden ska tas bort (elided) när squashing migrations.

Vi rekommenderar att du skriver koden som en separat funktion ovanför klassen Migration i migreringsfilen och skickar den till RunPython. Här är ett exempel på hur du använder RunPython för att skapa några initiala objekt på en Country-modell:

Code
from django.db import migrations


def forwards_func(apps, schema_editor):
    # We get the model from the versioned app registry;
    # if we directly import it, it'll be the wrong version
    Country = apps.get_model("myapp", "Country")
    db_alias = schema_editor.connection.alias
    Country.objects.using(db_alias).bulk_create(
        [
            Country(name="USA", code="us"),
            Country(name="France", code="fr"),
        ]
    )


def reverse_func(apps, schema_editor):
    # forwards_func() creates two Country instances,
    # so reverse_func() should delete them.
    Country = apps.get_model("myapp", "Country")
    db_alias = schema_editor.connection.alias
    Country.objects.using(db_alias).filter(name="USA", code="us").delete()
    Country.objects.using(db_alias).filter(name="France", code="fr").delete()


class Migration(migrations.Migration):
    dependencies = []

    operations = [
        migrations.RunPython(forwards_func, reverse_func),
    ]

Detta är i allmänhet den operation du skulle använda för att skapa datamigreringar, köra anpassade datauppdateringar och ändringar och allt annat du behöver tillgång till en ORM och/eller Python-kod för.

Precis som RunSQL, se till att om du ändrar schema här inne gör du det antingen utanför omfattningen av Djangos modellsystem (t.ex. triggers) eller att du använder SeparateDatabaseAndState för att lägga till operationer som återspeglar dina ändringar i modelltillståndet - annars kommer den versionerade ORM och autodetektorn att sluta fungera korrekt.

Som standard kommer RunPython att köra sitt innehåll inuti en transaktion på databaser som inte stöder DDL-transaktioner (till exempel MySQL och Oracle). Detta bör vara säkert, men kan orsaka en krasch om du försöker använda schema_editor som tillhandahålls på dessa backends; i detta fall, skicka atomic=False till RunPython-operationen.

På databaser som stöder DDL-transaktioner (SQLite och PostgreSQL) har RunPython -operationer inga transaktioner som automatiskt läggs till förutom de transaktioner som skapas för varje migrering. Således, till exempel på PostgreSQL, bör du undvika att kombinera schemaändringar och RunPython-operationer i samma migrering, annars kan du träffa fel som OperationalError: cannot ALTER TABLE "mytable" because it has pending trigger events.

Om du har en annan databas och inte är säker på om den stöder DDL-transaktioner, kontrollera attributet django.db.connection.features.can_rollback_ddl.

Om åtgärden RunPython är en del av en non-atomic migration, kommer åtgärden endast att utföras i en transaktion om atomic=True skickas till åtgärden RunPython.

static RunPython.noop()Link to this definition

Skicka metoden RunPython.noop till code eller reverse_code när du vill att operationen inte ska göra något i den angivna riktningen. Detta är särskilt användbart för att göra operationen reversibel.

SepareraDatabasOchStatusLink to this heading

class SeparateDatabaseAndState(database_operations=None, state_operations=None)Link to this definition

En mycket specialiserad operation som gör det möjligt att kombinera databasaspekter (schemaändring) och statliga aspekter (autodetektorkraft) av operationer.

Den accepterar två listor med operationer. När du blir ombedd att tillämpa tillstånd kommer den att använda listan `` state_operations`` (detta är en generaliserad version av RunSQL’s `` state_operations`` argument). När den ombeds att tillämpa ändringar i databasen kommer den att använda listan database_operations.

Om databasens faktiska tillstånd och Djangos syn på tillståndet inte är synkroniserade kan detta bryta migreringsramverket och till och med leda till dataförlust. Det är värt att vara försiktig och kontrollera dina databas- och tillståndsoperationer noggrant. Du kan använda sqlmigrate och dbshell för att kontrollera dina databasoperationer. Du kan använda makemigrations, särskilt med --dry-run, för att kontrollera dina tillståndsoperationer.

För ett exempel på användning av SeparateDatabaseAndState, se Ändra en ManyToManyField så att den använder en through-modell.

OperationskategoriLink to this heading

class OperationCategoryLink to this definition

Kategorier av migreringsoperationer som används av kommandot makemigrations för att visa meningsfulla symboler.

ADDITIONLink to this definition

Symbol: +

REMOVALLink to this definition

Symbol: -

ALTERATIONLink to this definition

Symbol: ~

PYTHONLink to this definition

Symbol: p

SQLLink to this definition

Symbol: s

MIXEDLink to this definition

Symbol: ?

Skriva din egenLink to this heading

Operationer har ett relativt enkelt API, och de är utformade så att du enkelt kan skriva dina egna för att komplettera de inbyggda Django. Den grundläggande strukturen för en Operation ser ut så här:

Code
from django.db.migrations.operations.base import Operation


class MyCustomOperation(Operation):
    # If this is False, it means that this operation will be ignored by
    # sqlmigrate; if true, it will be run and the SQL collected for its output.
    reduces_to_sql = False

    # If this is False, Django will refuse to reverse past this operation.
    reversible = False

    # This categorizes the operation. The corresponding symbol will be
    # displayed by the makemigrations command.
    category = OperationCategory.ADDITION

    def __init__(self, arg1, arg2):
        # Operations are usually instantiated with arguments in migration
        # files. Store the values of them on self for later use.
        pass

    def state_forwards(self, app_label, state):
        # The Operation should take the 'state' parameter (an instance of
        # django.db.migrations.state.ProjectState) and mutate it to match
        # any schema changes that have occurred.
        pass

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        # The Operation should use schema_editor to apply any changes it
        # wants to make to the database.
        pass

    def database_backwards(self, app_label, schema_editor, from_state, to_state):
        # If reversible is True, this is called when the operation is reversed.
        pass

    def describe(self):
        # This is used to describe what the operation does.
        return "Custom Operation"

    @property
    def migration_name_fragment(self):
        # Optional. A filename part suitable for automatically naming a
        # migration containing this operation, or None if not applicable.
        return "custom_operation_%s_%s" % (self.arg1, self.arg2)

Du kan ta den här mallen och arbeta utifrån den, men vi föreslår att du tittar på de inbyggda Django-operationerna i django.db.migrations.operations - de täcker mycket av exempelanvändningen av semi-interna aspekter av migreringsramen som ProjectState och de mönster som används för att få historiska modeller, liksom ModelState och de mönster som används för att mutera historiska modeller i state_forwards().

Några saker att notera:

  • Du behöver inte lära dig så mycket om ProjectState för att skriva migreringar; du behöver bara veta att den har en apps-egenskap som ger tillgång till ett appregister (som du sedan kan anropa get_model på).

  • database_forwards och database_backwards får båda två tillstånd skickade till sig; dessa representerar skillnaden som state_forwards-metoden skulle ha tillämpat, men ges till dig av bekvämlighets- och hastighetsskäl.

  • Om du vill arbeta med modellklasser eller modellinstanser från argumentet from_state i database_forwards() eller database_backwards() måste du rendera modelltillstånd med metoden clear_delayed_apps_cache() för att göra relaterade modeller tillgängliga:

    Code
    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        # This operation should have access to all models. Ensure that all models are
        # reloaded in case any are delayed.
        from_state.clear_delayed_apps_cache()
        ...
    
  • to_state i metoden database_backwards är det äldre tillståndet, det vill säga det som kommer att vara det aktuella tillståndet när migreringen har avslutats.

  • Du kan se implementeringar av references_model på de inbyggda operationerna; detta är en del av autodetekteringskoden och spelar ingen roll för anpassade operationer.

Låt oss som ett exempel göra en operation som laddar PostgreSQL-tillägg (som innehåller några av PostgreSQL: s mer spännande funktioner). Eftersom det inte finns några förändringar i modelltillståndet är allt det gör att köra ett kommando:

Code
from django.db.migrations.operations.base import Operation


class LoadExtension(Operation):
    reversible = True

    def __init__(self, name):
        self.name = name

    def state_forwards(self, app_label, state):
        pass

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        schema_editor.execute("CREATE EXTENSION IF NOT EXISTS %s" % self.name)

    def database_backwards(self, app_label, schema_editor, from_state, to_state):
        schema_editor.execute("DROP EXTENSION %s" % self.name)

    def describe(self):
        return "Creates extension %s" % self.name

    @property
    def migration_name_fragment(self):
        return "create_extension_%s" % self.name