Conas imirce bunachar sonraí a chruthúLink to this heading

Míníonn an doiciméad seo conas imirce bunachar sonraí a struchtúrú agus a scríobh do chásanna éagsúla a d'fhéad Le haghaidh ábhar tosaigh maidir le himirce, féach:doc: `an treoir ábhair `</topics/migrations>.

Imirce sonraí agus bunachair sonraí iolrachaLink to this heading

Agus bunachair sonraí iolracha á úsáid agat, b'fhéidir go mbeidh ort a fháil amach cibé acu imirce a reáchtáil i gcoinne bunachar sonraí áirithe nó Mar shampla, b'fhéidir gur mhaith leat imirce a reáchtáil** ar bhunachar sonraí áirithe.

D'fhonn é sin a dhéanamh is féidir leat ainm an nasc bunachar sonraí a sheiceáil taobh istigh d'oibríocht RunPython trí fhéachaint ar an tréith schema_editor.connection.alias`:

Code
from django.db import migrations


def forwards(apps, schema_editor):
    if schema_editor.connection.alias != "default":
        return
    # Your migration code goes here


class Migration(migrations.Migration):
    dependencies = [
        # Dependencies to other migrations
    ]

    operations = [
        migrations.RunPython(forwards),
    ]

You can also provide hints that will be passed to the allow_migrate() method of database routers as **hints:

myapp/dbrouters.py
Python
class MyRouter:
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if "target_db" in hints:
            return db == hints["target_db"]
        return True

Ansin, chun é seo a ghiaráil i do imirce, déan an méid seo a leanas:

Code
from django.db import migrations


def forwards(apps, schema_editor):
    # Your migration code goes here
    ...


class Migration(migrations.Migration):
    dependencies = [
        # Dependencies to other migrations
    ]

    operations = [
        migrations.RunPython(forwards, hints={"target_db": "default"}),
    ]

Mura ndéanann d'oibríocht `` RunPython`` nó `` RunSQL`` difear ach do mhúnla amháin, is dea-chleachtas é `` model_name`` a chur ar aghaidh mar leid chun é a dhéanamh chomh trédhearcach agus is féidir don ródaire. Tá sé seo tábhachtach go háirithe maidir le haipeanna ath-inúsáidte agus tríú páirtí.

Imirce a chuireann réimsí uathúla leisLink to this heading

Má chuirtear ascnamh “gnáth” i bhfeidhm a chuireann réimse uathúil neamh-neamhnithe le tábla le sraitheanna atá ann cheana féin, ardófar earráid mar ní ghintear an luach a úsáidtear chun sraitheanna atá ann cheana a líonadh ach uair amháin, rud a bhriseann an srian uathúil.

Dá bhrí sin, ba chóir na céimeanna seo a leanas a dhéanamh. Sa sampla seo, cuirfimid neamh-nullable:class: ~django.db.models.uuidfield le luach réamhshocraithe. Athraigh an réimse faoi seach de réir do riachtanas.

  • Cuir an réimse ar do mhúnla le default=uuid.uuid4` agus Unique=True argóintí (roghnaigh réamhshocrú cuí don chineál réimse atá á chur leis).

  • Rith an t-ordú:djadmin: makemigrations. Ba chóir go gcruthódh sé seo imirce le hoibríocht AddField.

  • Ginigh dhá chomhad imirce folamh don aip céanna trí makemigrations myapp --empty a reáchtáil faoi dhó. Rinneamar athainmniú na comhaid imirce chun ainmneacha bríocha a thabhairt dóibh sna samplaí thíos.

  • Cóipeáil an oibríocht AddField ón imirce uathoibríoch a ghintear (an chéad cheann de na trí chomhad nua) go dtí an imirce deireanach, athraigh Addfield go AlterField, agus cuir allmhairí uuid` agus samhlacha `. Mar shampla:

    0006_remove_uuid_null.py
    Python
    # Generated by Django A.B on YYYY-MM-DD HH:MM
    from django.db import migrations, models
    import uuid
    
    
    class Migration(migrations.Migration):
        dependencies = [
            ("myapp", "0005_populate_uuid_values"),
        ]
    
        operations = [
            migrations.AlterField(
                model_name="mymodel",
                name="uuid",
                field=models.UUIDField(default=uuid.uuid4, unique=True),
            ),
        ]
    
  • Cuir an chéad chomhad imirce in eagar. Ba chóir go mbeadh cuma cosúil leis seo ar an rang imirce ginte:

    0004_add_uuid_field.py
    Python
    class Migration(migrations.Migration):
        dependencies = [
            ("myapp", "0003_auto_20150129_1705"),
        ]
    
        operations = [
            migrations.AddField(
                model_name="mymodel",
                name="uuid",
                field=models.UUIDField(default=uuid.uuid4, unique=True),
            ),
        ]
    

    Athraigh unique=True go Null=True - cruthóidh sé seo an réimse null idirghabhálaí agus cuirfidh sé siar an srian uathúil a chruthú go dtí go mbeidh luachanna uathúla curtha againn ar na sraitheanna go léir.

  • Sa chéad chomhad imirce folamh, cuir a:class: ~django.db.migrations.operations.runpython nó:class: ~django.db.migrations.operations.runsql oibríocht chun luach uathúil (UUID sa sampla) a ghiniúint do gach sraith atá ann cheana. Cuir allmhairiú ``uuid ``leis freisin. Mar shampla:

    0005_populate_uuid_values.py
    Python
    # Generated by Django A.B on YYYY-MM-DD HH:MM
    from django.db import migrations
    import uuid
    
    
    def gen_uuid(apps, schema_editor):
        MyModel = apps.get_model("myapp", "MyModel")
        for row in MyModel.objects.all():
            row.uuid = uuid.uuid4()
            row.save(update_fields=["uuid"])
    
    
    class Migration(migrations.Migration):
        dependencies = [
            ("myapp", "0004_add_uuid_field"),
        ]
    
        operations = [
            # omit reverse_code=... if you don't want the migration to be reversible.
            migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop),
        ]
    
  • Anois is féidir leat na himirce a chur i bhfeidhm mar is gnách leis an ordú:djadmin: migrate.

    Tabhair faoi deara go bhfuil coinníoll rása ann má cheadaíonn tú rudaí a chruthú agus an imirce seo á rith. Beidh a “uuid” bunaidh forscríofa ag rudaí a cruthaíodh tar éis an Addfield agus roimh Runpython.

Imirce neamh-adamhachaLink to this heading

Ar bhunachair sonraí a thacaíonn le hidirbhearta DDL (SQLite agus PostgreSQL), rithfidh imirce taobh istigh d'idirbheart de réir réamhshocraithe. Maidir le cásanna úsáide mar imirce sonraí a dhéanamh ar tháblaí móra, b'fhéidir gur mhaith leat imirce a chosc ó rith in idirbheart tríd an tréith atomic` a shocrú do `False:

Code
from django.db import migrations


class Migration(migrations.Migration):
    atomic = False

Within such a migration, all operations are run without a transaction. It's possible to execute parts of the migration inside a transaction using atomic() or by passing atomic=True to RunPython.

Seo sampla d'imirce sonraí neamh-adamhacha a nuashonraíonn tábla mór i mbaisceanna níos lú:

Code
import uuid

from django.db import migrations, transaction


def gen_uuid(apps, schema_editor):
    MyModel = apps.get_model("myapp", "MyModel")
    while MyModel.objects.filter(uuid__isnull=True).exists():
        with transaction.atomic():
            for row in MyModel.objects.filter(uuid__isnull=True)[:1000]:
                row.uuid = uuid.uuid4()
                row.save()


class Migration(migrations.Migration):
    atomic = False

    operations = [
        migrations.RunPython(gen_uuid),
    ]

Níl éifeacht ag an tréith atomic ar bhunachair sonraí nach dtacaíonn le hidirbhearta DDL (m.sh. MySQL, Oracle). (Tagraíonn “tacaíocht ráiteas DDL adamhach” MySQL < https://dev.mysql.com/doc/refman/en/atomic-ddl.html> do ráitis aonair seachas ráitis iolracha atá fillte in idirbheart is féidir a rolladh ar ais.)

Ord na n-imirce a rialúLink to this heading

Cinneann Django an t-ord ina gcaithfear imirce a chur i bhfeidhm ní trí ainm comhaid gach imirce, ach trí graf a thógáil ag baint úsáide as dhá airíonna ar an aicme Imigration: dependencies` agus ``run_before ``.

Má d'úsáid tú an t-ordú:djadmin: makemigrations is dócha go bhfaca tú dependencies i ngníomh cheana féin toisc go bhfuil sé seo sainmhínithe ag imirce uathoibríoch mar chuid dá bpróiseas cruthaithe.

Dearbhaítear an maoin `spleáchais ``mar seo:

Code
from django.db import migrations


class Migration(migrations.Migration):
    dependencies = [
        ("myapp", "0123_the_previous_migration"),
    ]

De ghnáth beidh sé seo go leor, ach ó am go ham b'fhéidir go gcaithfidh tú a chinntiú go ritheann d'imirce* roim* imirce eile. Tá sé seo úsáideach, mar shampla, chun imirce feidhmchláir tríú páirtí a reáchtáil* tar éis d'athsholáthar your:setting: AUTH_USER_MODEL.

Chun é seo a bhaint amach, cuir na himirce go léir ar chóir a bheith ag brath ar leatsa sa tréith run_before ``ar do rang ``Immigration:

Code
class Migration(migrations.Migration):
    ...

    run_before = [
        ("third_party_app", "0001_do_awesome"),
    ]

Is fearr leat dependencies a úsáid seachas run_before ``nuair is féidir. Níor cheart duit ``run_before ``a úsáid ach mura bhfuil inmhianaithe neamhphraiticiúil ``spleáchais a shonrú san imirce a theastaíonn uait a reáchtáil tar éis an ceann atá á scríobh agat.

Sonraí a imirce idir apps tríú páirtíLink to this heading

Is féidir leat imirce sonraí a úsáid chun sonraí a aistriú ó fheidhmchlár tríú páirtí amháin go ceann eile.

Má tá sé ar intinn agat an sean-aip a bhaint níos déanaí, beidh ort an maoin spleáchais ``a shocrú bunaithe ar cibé an bhfuil an sean-aip suiteáilte nó nach bhfuil. Seachas sin, beidh spleáchais in easnamh agat nuair a dhíshuiteálann tú an sean-aip. Ar an gcaoi chéanna, beidh ort: exc: `LookuPerror a ghabháil sa ghlao ``apps.get_model () ``a aisghabhann samhlacha ón sean-aip. Ligeann an cur chuige seo duit do thionscadal a imscaradh áit ar bith gan an sean-aip a shuiteáil agus ansin a dhíshuiteáil.

Seo imirce samplach:

myapp/imirceach/0124_move_old_app_to_new_app.py
Python
from django.apps import apps as global_apps
from django.db import migrations


def forwards(apps, schema_editor):
    try:
        OldModel = apps.get_model("old_app", "OldModel")
    except LookupError:
        # The old app isn't installed.
        return

    NewModel = apps.get_model("new_app", "NewModel")
    NewModel.objects.bulk_create(
        NewModel(new_attribute=old_object.old_attribute)
        for old_object in OldModel.objects.all()
    )


class Migration(migrations.Migration):
    operations = [
        migrations.RunPython(forwards, migrations.RunPython.noop),
    ]
    dependencies = [
        ("myapp", "0123_the_previous_migration"),
        ("new_app", "0001_initial"),
    ]

    if global_apps.is_installed("old_app"):
        dependencies.append(("old_app", "0001_initial"))

Smaoinigh freisin ar cad ba mhaith leat a tharlóidh nuair nach gcuirtear an imirce i bhfeidhm. D'fhéadfá aon rud a dhéanamh (mar atá sa sampla thuas) nó cuid de na sonraí nó go léir a bhaint as an bhfeidhmchlár nua. Coigeartaigh an dara argóint den oibríocht: mod: ~django.db.migrations.operations.runpython dá réir.

Athrú `ManyTomanyField chun samhail ``trí ``a úsáidLink to this heading

If you change a ManyToManyField to use a through model, the default migration will delete the existing table and create a new one, losing the existing relations. To avoid this, you can use SeparateDatabaseAndState to rename the existing table to the new table name while telling the migration autodetector that the new model has been created. You can check the existing table name and constraint name through sqlmigrate or dbshell. You can check the new table name with the through model's _meta.db_table property. Your new through model should use the same names for the ForeignKeys as Django did. Also if it needs any extra fields, they should be added in operations after SeparateDatabaseAndState.

Mar shampla, dá mbeadh samhail Leabhar againn le ManyTomanyField ag nascadh le Author ``, d'fhéadfaimis samhail tríd ``Authorbook a chur leis le réimse nua is_primary, mar shampla:

Code
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):
    dependencies = [
        ("core", "0001_initial"),
    ]

    operations = [
        migrations.SeparateDatabaseAndState(
            database_operations=[
                # Old table name from checking with sqlmigrate, new table
                # name from AuthorBook._meta.db_table.
                migrations.RunSQL(
                    sql="ALTER TABLE core_book_authors RENAME TO core_authorbook",
                    reverse_sql="ALTER TABLE core_authorbook RENAME TO core_book_authors",
                ),
            ],
            state_operations=[
                migrations.CreateModel(
                    name="AuthorBook",
                    fields=[
                        (
                            "id",
                            models.AutoField(
                                auto_created=True,
                                primary_key=True,
                                serialize=False,
                                verbose_name="ID",
                            ),
                        ),
                        (
                            "author",
                            models.ForeignKey(
                                on_delete=django.db.models.deletion.DO_NOTHING,
                                to="core.Author",
                            ),
                        ),
                        (
                            "book",
                            models.ForeignKey(
                                on_delete=django.db.models.deletion.DO_NOTHING,
                                to="core.Book",
                            ),
                        ),
                    ],
                    options={
                        "constraints": [
                            models.UniqueConstraint(
                                fields=["author", "book"],
                                name="unique_author_book",
                            )
                        ],
                    },
                ),
                migrations.AlterField(
                    model_name="book",
                    name="authors",
                    field=models.ManyToManyField(
                        to="core.Author",
                        through="core.AuthorBook",
                    ),
                ),
            ],
        ),
        migrations.AddField(
            model_name="authorbook",
            name="is_primary",
            field=models.BooleanField(default=False),
        ),
    ]

Samhail neamh-bhainistithe a athrú go bainistitheLink to this heading

Más mian leat samhail neamhbhainistithe (:attr: managed=false <django.db.models.Options.managed>) a athrú go bainistithe, ní mór duit Managed = False` a bhaint agus imirce a ghiniúint sula ndéanann tú athruithe eile a bhaineann le scéim ar an tsamhail, ós rud é nach féidir athruithe scéime atá le feiceáil san imirce ina bhfuil an oibríocht chun `Meta.Managed ``a athrú.