Як перемістити модель між двома програмами Django (Django 1.7)


133

Отож, близько року тому я розпочав проект і, як і всі нові розробники, я не надто зосереджувався на структурі, проте тепер я разом із Django почав здаватися, що в основному мої моделі мають жахливу структуру .

У мене моделі в основному містяться в одному додатку, і справді більшість цих моделей повинні бути у власних індивідуальних програмах, я намагався вирішити це і переміщувати їх на південь, однак мені здалося, що це складно і дуже складно через закордонних ключів.

Однак завдяки Django 1.7 та побудованій підтримці міграцій є кращий спосіб зробити це зараз?


4
Ви можете розглянути можливість зміни відповіді.
Бабкен Варданян

Для людей, які стикаються з цим у майбутньому: Django 3.x тут, і підхід, детальний на realpython.com/move-django-model/…, працював на мене. У мене було кілька іноземних ключів між моделями в старій програмі та моделями в новому додатку.
pradeepcep

Відповіді:


16

Я видаляю стару відповідь, оскільки це може призвести до втрати даних. Як згадував Озан , ми можемо створити 2 міграції по одній у кожному додатку. Зауваження, що знаходяться під цією публікацією, стосуються моєї старої відповіді.

Перша міграція для видалення моделі з 1-го додатка.

$ python manage.py makemigrations old_app --empty

Відредагуйте файл міграції, щоб включити ці операції.

class Migration(migrations.Migration):

    database_operations = [migrations.AlterModelTable('TheModel', 'newapp_themodel')]

    state_operations = [migrations.DeleteModel('TheModel')]

    operations = [
      migrations.SeparateDatabaseAndState(
        database_operations=database_operations,
        state_operations=state_operations)
    ]

Друга міграція, яка залежить від першої міграції, і створити нову таблицю у другому додатку. Після переміщення коду моделі до другого додатка

$ python manage.py makemigrations new_app 

і відредагуйте файл міграції на щось подібне.

class Migration(migrations.Migration):

    dependencies = [
        ('old_app', 'above_migration')
    ]

    state_operations = [
        migrations.CreateModel(
            name='TheModel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ],
            options={
                'db_table': 'newapp_themodel',
            },
            bases=(models.Model,),
        )
    ]

    operations = [
        migrations.SeparateDatabaseAndState(state_operations=state_operations)
    ]

У мене є існуючі дані, і багато з них я просто не можу втратити, можливо, це зробити з цим?
Сем Бакінгем

@KevinChristopherHenry Змінив код. Це зберігає наявні дані.
ChillarAnand

@SamBuckingham Так, ви можете спробувати змінити код, щоб перейти, не втрачаючи дані.
ChillarAnand

2
Я думаю, що це стане найкращим способом, дякую за всю допомогу хлопцям, яка була блискучою.
Сем Бакінгем

1
ІМО - це неправильне рішення, основне припущення про міграцію полягає в тому, що якщо запустити, ./manage.py migrateвсе закінчиться в хорошому стані. Підробка міграцій вручну - це ІМО - неправильний шлях.
jb.

341

Це можна зробити досить легко, використовуючи migrations.SeparateDatabaseAndState . В основному ми використовуємо операцію з базою даних для перейменування таблиці одночасно з двома операціями стану, щоб вилучити модель з історії однієї програми та створити її в іншій.

Видалити зі старого додатка

python manage.py makemigrations old_app --empty

Під час міграції:

class Migration(migrations.Migration):

    dependencies = []

    database_operations = [
        migrations.AlterModelTable('TheModel', 'newapp_themodel')
    ]

    state_operations = [
        migrations.DeleteModel('TheModel')
    ]

    operations = [
        migrations.SeparateDatabaseAndState(
            database_operations=database_operations,
            state_operations=state_operations)
    ]

Додати в нову програму

Спочатку скопіюйте модель у model.py нового додатка, потім:

python manage.py makemigrations new_app

Це призведе до міграції з наївом CreateModel операцією як єдиною операцією. Заверніть це в SeparateDatabaseAndStateоперації таким чином, щоб ми не намагалися відтворити таблицю. Також включайте попередню міграцію як залежність:

class Migration(migrations.Migration):

    dependencies = [
        ('old_app', 'above_migration')
    ]

    state_operations = [
        migrations.CreateModel(
            name='TheModel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ],
            options={
                'db_table': 'newapp_themodel',
            },
            bases=(models.Model,),
        )
    ]

    operations = [
        migrations.SeparateDatabaseAndState(state_operations=state_operations)
    ]

14
Дійсно гарне пояснення. Це має бути відповіддю, перейменуючи таблицю, ви уникаєте втрати будь-яких даних.
Реміз

11
Це найкращий спосіб зробити це, і це набагато краще, ніж мій. Додана примітка вгорі моєї відповіді.
ChillarAnand

4
Я зробив це, але коли я запускаю "makemigrations" на newapp після цього, він генерує міграцію AlterModelTable, перейменуючи її на None.
Дієго Пончано

4
Знайшов спосіб вирішити свою проблему на основі цих інструкцій. Проблема складніша, якщо у вас є посилання на закордонні ключі, які обов'язкові для заповнення. Мені довелося додати пару кроків, щоб перемістити посилання.
Nostalg.io

14
Через багато запитів я створив детальну відповідь на міграцію моделі FK на прикладі GitHub. stackoverflow.com/questions/30601107 / ...
Nostalg.io

26

Я зіткнувся з тією ж проблемою. Відповідь Озана мені дуже допомогла, але, на жаль, була недостатньою. Дійсно, у мене було декілька іноземних ключів до моделі, яку я хотів перейти. Після деякого головного болю я знайшов рішення, тому вирішив опублікувати його, щоб вирішити час людей.

Вам потрібно ще 2 кроки:

  1. Перш ніж щось робити, змініть усі свої ForeignKeyпосилання TheModelна Integerfield. Потім бігайтеpython manage.py makemigrations
  2. Виконуючи кроки Озана, конвертуйте свої закордонні ключі: поставте назад ForeignKey(TheModel)замість IntegerField(). Потім знову зробіть міграцію ( python manage.py makemigrations). Потім ви можете мігрувати, і це має працювати ( python manage.py migrate)

Сподіваюся, це допомагає. Звичайно, протестуйте його на місцевому рівні, перш ніж спробувати у виробництві, щоб уникнути поганих сюрпризів :)


8
як щодо відносин ManyToManyField ??
tomcounsell

1
@tomcounsell чудовий коментар, я б припустив, додавши конкретну модель через цілі міграції. Потрібно багато роботи, щоб залишити дані недоторканими ...
Wtower

Оскільки відносини «багато-багато» зазвичай є лише таблицею з двома зовнішніми ключами, з точки зору SQL ви можете застосувати фокус цієї відповіді. Але для того, щоб досягти цього лише через Django, один підхід, який я можу придумати, був би за принципом відповіді @ozan, за винятком того, що першим кроком було б дублювання таблиць, що беруть участь у взаємовідносинах MTM (по одній версії дупи в кожному додатку) , перемістіть усі іноземні ключі до нового додатку і лише після цього видаліть олівці зі старого додатка. Відмова: Я не тестував :)
Арно П

15

Як я це зробив (тестував на Django == 1,8, з postgres, напевно, також 1,7)

Ситуація

app1.YourModel

але ви хочете, щоб він перейшов до: app2.YourModel

  1. Скопіюйте YourModel (код) з app1 в app2.
  2. додайте це до app2.YourModel:

    Class Meta:
        db_table = 'app1_yourmodel'
  3. $ python Manag.py makemigrations app2

  4. Нова міграція (наприклад, 0009_auto_something.py) робиться в додатку2 з оператором migrations.CreateModel (), перемістіть цей оператор до початкової міграції app2 (наприклад, 0001_initial.py) (це буде так само, як завжди було там). А тепер видаліть створену міграцію = 0009_auto_something.py

  5. Так само, як ви дієтесь, як app2.YourModel завжди був там, тепер зніміть існування app1.YourModel від міграцій. Значення: коментуйте заяви CreateModel, а також будь-яке коригування або перенесення даних, яке ви використовували після цього.

  6. І звичайно, кожне посилання на app1.YourModel має бути змінено на app2.YourModel через ваш проект. Крім того, не забувайте, що всі можливі зовнішні ключі до app1.YourModel під час міграцій повинні бути змінені на app2.YourModel

  7. Тепер, якщо ви переміщуєте $ python Manag.py, нічого не змінилося, також, коли ви робите $ python Manag.py макеміграції, нічого нового не виявлено.

  8. Тепер завершальний штрих: видаліть Class Meta з app2.YourModel і зробіть $ python Manag.py makemigrations app2 && python Manag.py migrate app2 (якщо ви заглянете в цю міграцію, ви побачите щось подібне :)

        migrations.AlterModelTable(
        name='yourmodel',
        table=None,
    ),

table = Немає, значить, вона буде приймати ім'я таблиці за замовчуванням, яке в цьому випадку буде app2_yourmodel.

  1. Зроблено, зроблено із збереженими даними.

PS під час міграції побачить, що цей content_type app1.yourmodel був видалений і його можна видалити. Ви можете сказати "так", але тільки якщо ви не використовуєте його. Якщо ви сильно залежите від цього, щоб FK-файли для цього типу контенту були недоторканими, не відповідайте "так" або "ні", але заходьте в db цей час вручну, і видаліть contentype app2.yourmodel і перейменуйте зміст app1. yourmodel до app2.yourmodel, а потім продовжуйте, відповівши "ні".


3
Хоча це рішення, безумовно, "хакірніше", ніж @ ozan, і воно, безумовно, потребує більшого редагування, для мене воно непогано працювало (і це нормально, щоб редагувати міграції - вони повинні редагуватися, згідно з документами).
pgcd

1
Можливо, також використовувати app_label = 'app1'мета-варіант.
Wtower

Геній! Це для мене чудово спрацювало для стосунків ForeignKey. Я думаю, це також буде працювати і для полів ManyToMany.
Бабкен Варданян

Я дотримувався ваших кроків, але поле в деякій моделі, що належить до app1, складається із зовнішнього ключа з рекурсивним відношенням до моделі (myModel), яку потрібно перемістити. Як і field1 = models.ForeignKey('app1.myModel').коли я field1 was declared with a lazy reference to 'app1.myModel' but app 'app1' doesn't provide model 'MyModel'
мігрую

12

У мене виникають нервові міграції ручного кодування (як того вимагає відповідь Озана ), тому наступне поєднує стратегії Озана та Майкла, щоб мінімізувати кількість необхідного кодування вручну:

  1. Перш ніж рухати будь-які моделі, переконайтеся, що ви працюєте з чистою базовою лінією, запустивши makemigrations.
  2. Перемістіть код для Моделі з app1доapp2
  3. Як рекомендує @Michael, ми вказуємо нову модель на стару таблицю бази даних, використовуючи параметр db_tableMeta на "новій" моделі:

    class Meta:
        db_table = 'app1_yourmodel'
  4. Біжи makemigrations. Це призведе CreateModelдо app2і DeleteModelв, і в app1. Технічно ці міграції стосуються точно такої самої таблиці і видаляють (включаючи всі дані) та знову створюють таблицю.

  5. Насправді ми не хочемо (або потребувати) нічого робити за столом. Нам просто потрібен Джанго, щоб повірити, що зміни відбулися. Відповідь Пер @ Озана, state_operationsпрапор SeparateDatabaseAndStateробить це. Таким чином , ми обертаємо все migrationsзаписи В ОБИДВА Міграції FILES з SeparateDatabaseAndState(state_operations=[...]). Наприклад,

    operations = [
        ...
        migrations.DeleteModel(
            name='YourModel',
        ),
        ...
    ]

    стає

    operations = [
        migrations.SeparateDatabaseAndState(state_operations=[
            ...
            migrations.DeleteModel(
                name='YourModel',
            ),
            ...
        ])
    ]
  6. Вам також потрібно переконатися, що нова "віртуальна" CreateModelміграція залежить від будь-якої міграції, яка фактично створила або змінила оригінальну таблицю . Наприклад, якщо ваші нові міграції app2.migrations.0004_auto_<date>(для Create) та app1.migrations.0007_auto_<date>(для Delete), найпростіше зробити:

    • Відкрийте app1.migrations.0007_auto_<date>та скопіюйте її app1залежність (наприклад ('app1', '0006...'),). Це "безпосередньо попередня" міграція в Росіїapp1 і повинна включати залежності від усієї фактичної логіки побудови моделі.
    • Відкрийте app2.migrations.0004_auto_<date>та додайте залежність, яку ви щойно скопіювали, до її dependenciesсписку.

Якщо у вас є ForeignKeyстосунки з моделлю, яку ви рухаєте, вищезгадане може не працювати. Це відбувається тому, що:

  • Залежності не створюються автоматично для ForeignKey змін
  • Ми не хочемо завершувати ForeignKeyзміни, state_operationsтому нам потрібно переконатися, що вони є окремими від операцій з таблицею.

ПРИМІТКА. Django 2.2 додав попередження ( models.E028), яке порушує цей метод. Можливо, ви зможете обійтись із цим, managed=Falseале я його не перевіряв.

"Мінімальний" набір операцій відрізняється залежно від ситуації, але наступна процедура повинна працювати для більшості / всіх ForeignKeyміграцій:

  1. COPY модель від app1до app2, наборуdb_table , але не змінювати будь-які посилання FK.
  2. Запустіть makemigrationsі заверніть всю app2міграцію вstate_operations (див. Вище)
    • Як вище, додайте залежність app2 CreateTableдо останньої app1міграції
  3. Вкажіть усі посилання FK на нову модель. Якщо ви не використовуєте посилання рядків, перемістіть стару модель внизуmodels.py (НЕ видаляйте її), щоб вона не конкурувала з імпортованим класом.
  4. Запустіть, makemigrationsале НЕ вкладайте нічого state_operations(зміни ФК насправді повинні відбутися). Додайте залежність від усіх ForeignKeyміграцій (тобто AlterField) до CreateTableміграції в app2(вам знадобиться цей список для наступного кроку, тому слідкуйте за ними). Наприклад:

    • Знайдіть міграцію, яка включає CreateModelнапрapp2.migrations.0002_auto_<date> І скопіюйте її ім'я.
    • Знайдіть усі міграції, які мають ForeignKey до цієї моделі (наприклад, шляхом пошуку app2.YourModelміграцій, таких як:

      class Migration(migrations.Migration):
      
          dependencies = [
              ('otherapp', '0001_initial'),
          ]
      
          operations = [
              migrations.AlterField(
                  model_name='relatedmodel',
                  name='fieldname',
                  field=models.ForeignKey(... to='app2.YourModel'),
              ),
          ]
    • Додайте CreateModelміграцію як залежність:

      class Migration(migrations.Migration):
      
          dependencies = [
              ('otherapp', '0001_initial'),
              ('app2', '0002_auto_<date>'),
          ]  
  5. Видаліть моделі з app1

  6. Запустіть makemigrationsі заверніть app1міграціюstate_operations .
    • Додайте залежність до всіх ForeignKeyміграцій (тобто AlterField) від попереднього кроку (може включати міграції в app1та app2).
    • Коли я будував ці міграції, то DeleteTableвже залежав від AlterFieldміграцій, тому мені не потрібно було вручну їх виконувати (тобто Alterраніше Delete).

У цей момент Джанго добре піти. Нова модель вказує на старий стіл, і міграції Джанго переконали, що все було переселено належним чином. Велике застереження (з відповіді @ Майкла) полягає в ContentTypeтому, що для нової моделі створено нове. Якщо ви пов'язуєте (наприклад, за ForeignKey) типи вмісту, вам потрібно створити міграцію для оновлення ContentTypeтаблиці.

Я хотів очистити після себе (параметри мета та назви таблиць), тому я застосував таку процедуру (від @Michael):

  1. Видаліть db_tableзапис Meta
  2. Запустіть makemigrationsще раз, щоб створити перейменування бази даних
  3. Відредагуйте останню міграцію та переконайтесь, що вона залежить від DeleteTableміграції. Це не здається, що це повинно бути необхідним, оскільки Deleteмає бути чисто логічним, але я зіткнувся з помилками (наприклад app1_yourmodel, не існує), якщо я цього не роблю.

Це спрацювало чудово, дякую! Я не думаю, що редагування останньої міграції має значення, оскільки це все-таки внизу дерева залежності.
Джеймс Мекін

1
Хороша відповідь! Я думаю, вам потрібно додати закриваючу дужку до міграцій. ВиділитиDatabaseAndState, правда?
атм

Це працювало для мене. Я також не редагував останню міграцію (крок 3, останній рядок усієї відповіді), як @JamesMeakin, і вона все ще спрацювала нормально
Megawatt

у другому сценарії - той, у якого є FKs, другий крок для мене провалився з помилкою, яка має сенс:table_name: (models.E028) db_table 'table_name' is used by multiple models: app1.Model, app2.Model.
Mihai Zamfir

Я кілька разів користувався процедурою. Якщо порівняти документацію для 2.2 ( docs.djangoproject.com/en/2.2/ref/checks ) та 2.1 ( docs.djangoproject.com/en/2.1/ref/checks ), ви можете побачити, що вона була додана в 2.2. Можливо, можна обійтися, managed=Falseале мені нікуди це не перевірити.
claytond

1

Ще одна хитра альтернатива, якщо дані не є великими або занадто складними, але все ще важливими для підтримки, є:

  • Отримайте світильники даних за допомогою dumpdata Manag.py
  • Перейдіть до моделювання змін та міграцій належним чином, не пов’язуючи зміни
  • Глобальна заміна світильників зі старої моделі та назв додатків на нову
  • Завантажте дані за допомогою даних data.py loaddata

1

Скопійовано з моєї відповіді на https://stackoverflow.com/a/47392970/8971048

Якщо вам потрібно перемістити модель, і ви більше не маєте доступу до програми (або ви не хочете доступу), ви можете створити нову операцію і розглянути можливість створити нову модель, лише якщо перенесена модель не існують.

У цьому прикладі я передаю 'MyModel' від old_app до myapp.

class MigrateOrCreateTable(migrations.CreateModel):
    def __init__(self, source_table, dst_table, *args, **kwargs):
        super(MigrateOrCreateTable, self).__init__(*args, **kwargs)
        self.source_table = source_table
        self.dst_table = dst_table

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        table_exists = self.source_table in schema_editor.connection.introspection.table_names()
        if table_exists:
            with schema_editor.connection.cursor() as cursor:
                cursor.execute("RENAME TABLE {} TO {};".format(self.source_table, self.dst_table))
        else:
            return super(MigrateOrCreateTable, self).database_forwards(app_label, schema_editor, from_state, to_state)


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0002_some_migration'),
    ]

    operations = [
        MigrateOrCreateTable(
            source_table='old_app_mymodel',
            dst_table='myapp_mymodel',
            name='MyModel',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=18))
            ],
        ),
    ]

Не додайте однакову відповідь на кілька запитань. Дайте відповідь найкращому, а решту позначте як дублікати. Див. Чи прийнятно додати дублюючу відповідь на кілька запитань?
Петтер Фріберг

0

Це перевірено орієнтовно, тому не забудьте зробити резервну копію вашої БД !!!

Наприклад, є дві програми: src_appі dst_appми хочемо перенести модель MoveMeз src_appнаdst_app .

Створіть порожні міграції для обох додатків:

python manage.py makemigrations --empty src_app
python manage.py makemigrations --empty dst_app

Давайте припустимо, що нові сценарії перенастроювання XXX1_src_app_newі XXX1_dst_app_new, previuos верхньої міграції є XXX0_src_app_oldіXXX0_dst_app_old .

Додайте операцію, яка перейменовує таблицю для MoveMeмоделі та перейменовує її app_label в ProjectState до XXX1_dst_app_new. Не забудьте додати залежність від XXX0_src_app_oldміграції. Отримана XXX1_dst_app_newміграція:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

# this operations is almost the same as RenameModel
# https://github.com/django/django/blob/1.7/django/db/migrations/operations/models.py#L104
class MoveModelFromOtherApp(migrations.operations.base.Operation):

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

    def state_forwards(self, app_label, state):

        # Get all of the related objects we need to repoint
        apps = state.render(skip_cache=True)
        model = apps.get_model(self.old_app_label, self.name)
        related_objects = model._meta.get_all_related_objects()
        related_m2m_objects = model._meta.get_all_related_many_to_many_objects()
        # Rename the model
        state.models[app_label, self.name.lower()] = state.models.pop(
            (self.old_app_label, self.name.lower())
        )
        state.models[app_label, self.name.lower()].app_label = app_label
        for model_state in state.models.values():
            try:
                i = model_state.bases.index("%s.%s" % (self.old_app_label, self.name.lower()))
                model_state.bases = model_state.bases[:i] + ("%s.%s" % (app_label, self.name.lower()),) + model_state.bases[i+1:]
            except ValueError:
                pass
        # Repoint the FKs and M2Ms pointing to us
        for related_object in (related_objects + related_m2m_objects):
            # Use the new related key for self referential related objects.
            if related_object.model == model:
                related_key = (app_label, self.name.lower())
            else:
                related_key = (
                    related_object.model._meta.app_label,
                    related_object.model._meta.object_name.lower(),
                )
            new_fields = []
            for name, field in state.models[related_key].fields:
                if name == related_object.field.name:
                    field = field.clone()
                    field.rel.to = "%s.%s" % (app_label, self.name)
                new_fields.append((name, field))
            state.models[related_key].fields = new_fields

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        old_apps = from_state.render()
        new_apps = to_state.render()
        old_model = old_apps.get_model(self.old_app_label, self.name)
        new_model = new_apps.get_model(app_label, self.name)
        if self.allowed_to_migrate(schema_editor.connection.alias, new_model):
            # Move the main table
            schema_editor.alter_db_table(
                new_model,
                old_model._meta.db_table,
                new_model._meta.db_table,
            )
            # Alter the fields pointing to us
            related_objects = old_model._meta.get_all_related_objects()
            related_m2m_objects = old_model._meta.get_all_related_many_to_many_objects()
            for related_object in (related_objects + related_m2m_objects):
                if related_object.model == old_model:
                    model = new_model
                    related_key = (app_label, self.name.lower())
                else:
                    model = related_object.model
                    related_key = (
                        related_object.model._meta.app_label,
                        related_object.model._meta.object_name.lower(),
                    )
                to_field = new_apps.get_model(
                    *related_key
                )._meta.get_field_by_name(related_object.field.name)[0]
                schema_editor.alter_field(
                    model,
                    related_object.field,
                    to_field,
                )

    def database_backwards(self, app_label, schema_editor, from_state, to_state):
        self.old_app_label, app_label = app_label, self.old_app_label
        self.database_forwards(app_label, schema_editor, from_state, to_state)
        app_label, self.old_app_label = self.old_app_label, app_label

    def describe(self):
        return "Move %s from %s" % (self.name, self.old_app_label)


class Migration(migrations.Migration):

    dependencies = [
       ('dst_app', 'XXX0_dst_app_old'),
       ('src_app', 'XXX0_src_app_old'),
    ]

    operations = [
        MoveModelFromOtherApp('MoveMe', 'src_app'),
    ]

Додати залежність від XXX1_dst_app_newдо XXX1_src_app_new. XXX1_src_app_newце міграція без використання, яка необхідна для того, щоб переконатися, що майбутні src_appміграції будуть виконані після XXX1_dst_app_new.

Переміщення MoveMeвід src_app/models.pyдо dst_app/models.py. Потім запустіть:

python manage.py migrate

Це все!


Зауважте, що цей код, ймовірно, корисний лише для django 1.7. Спробувати це у django 2.0 не вийде. Це також означає, що використання цього механізму для переміщення моделей додає накладні витрати на оновлення вашої версії джанго.
Пол у 't Hout

0

Ви можете спробувати наступне (неперевірене):

  1. перемістити модель з src_appнаdest_app
  2. мігрувати dest_app; переконайтеся, що міграція схеми залежить від останньої src_appміграції ( https://docs.djangoproject.com/en/dev/topics/migrations/#migration-files )
  3. додати міграцію даних, до dest_appякої копіюються всі даніsrc_app
  4. мігрувати src_app; переконайтеся, що міграція схеми залежить від останньої міграції (даних) dest_app- тобто міграції кроку 3

Зауважте, що ви будете копіювати всю таблицю, а не переміщувати її, але таким чином обидва додатки не повинні торкатися таблиці, що належить іншому додатку, що я вважаю важливішим.


0

Скажімо, ви переміщуєте модель TheModel з app_a в app_b.

Альтернативним рішенням є вручну змінити існуючі міграції. Ідея полягає в тому, що кожного разу, коли ви бачите операцію, що змінює TheModel під час міграцій app_a, ви копіюєте цю операцію до кінця початкової міграції app_b. І кожного разу, коли ви бачите посилання "app_a.TheModel" під час міграцій app_a, ви змінюєте його на "app_b.TheModel".

Я щойно зробив це для вже існуючого проекту, де хотів витягти певну модель у програму для багаторазового використання. Процедура пройшла без проблем. Я думаю, що все було б набагато складніше, якби були посилання від app_b до app_a. Крім того, у мене був встановлений вручну мета.db_table для моєї моделі, що могло б допомогти.

Зокрема, ви отримаєте змінену історію міграції. Це не має значення, навіть якщо у вас є база даних із застосованими оригінальними міграціями. Якщо і оригінальні, і переписані міграції закінчуються однаковою схемою бази даних, тоді таке перезапис має бути ОК.


0
  1. змінити назви старих моделей на 'model_name_old'
  2. макеміграції
  3. створити нові моделі під назвою 'model_name_new' з однаковими відносинами на відповідних моделях (наприклад, у моделі користувача тепер є user.blog_old та user.blog_new)
  4. макеміграції
  5. написати спеціальну міграцію, яка переміщує всі дані до нових модельних таблиць
  6. перевірити пекло цих міграцій, порівнявши резервні копії з новими копіями db до та після запуску міграцій
  7. коли все задовільно, видаліть старі моделі
  8. макеміграції
  9. змінити нові моделі на правильну назву 'model_name_new' -> 'model_name'
  10. протестуйте всю кількість міграцій на сервері встановлення
  11. зніміть свій виробничий майданчик на кілька хвилин, щоб запустити всі міграції, не втручаючись користувачів

Зробіть це індивідуально для кожної моделі, яку потрібно перемістити. Я б не пропонував робити те, що говорить інша відповідь, змінюючи цілі числа та повертаючись на іноземні ключі. Є ймовірність, що нові зовнішні ключі будуть іншими, а рядки можуть мати різні ідентифікатори після міграції, і я не хотів ризикувати невідповідності ідентифікаторів при переході назад на зовнішні ключі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.