Как мигрировать с юга при использовании «через» для поля ManyToMany? - PullRequest
5 голосов
/ 24 октября 2011

Я хочу изменить поле ManyToMany в приложении django.

У меня есть следующие модели:

class A:
    ...

class B:
    as = models.ManyToManyField(A)

и я хочу:

class A:
    ...

class C:
     a = models.ForeignKey(A)
     b = models.ForeignKey("B")
     extra_data = models.BooleanField(default=False)

class B:
    as = models.ManyToManyField(A, through=C)

Я использую юг для миграции БД. К сожалению, в этом случае южная сторона предлагает удалить существующую таблицу app_b_a и воссоздать новую app_c.

Есть ли способ сказать югу не воссоздавать таблицу m2m?

Ответы [ 3 ]

6 голосов
/ 24 октября 2011

Я бы попытался сделать это следующим образом:

  1. Добавить модель C, но не добавить еще какие-либо дополнительные поля данных.Просто установите 2 FK для связанных моделей, чтобы схема по сути была идентична таблице m2m по умолчанию, за исключением имени таблицы.
  2. Выполните schemamigration --auto для вашего приложения.
  3. Чтобы эффективно "удалите «существующую таблицу и« создайте »новую, не перемещая данные, просто удалите все сгенерированные коды миграции из методов forwards / backwards и добавьте: forward: db.rename_table('yourappname_m2mtablename', 'yourappname_c') в обратном направлении: db.rename_table('yourappname_c', 'yourappname_m2mtablename')
  4. Оставьте "замороженные" модели такими, какие они есть!
  5. Теперь вы можете расширить модель C и сгенерировать для нее новую схему.
2 голосов
/ 24 октября 2011

Только недавно пришлось сделать это самому. Это на самом деле довольно легко.

Сначала добавьте новую сквозную модель в ваш код, но не задайте его как параметр through для вашего ManyToManyField. Создайте автоматическую схему миграции, которая создаст новую таблицу для вас.

$ python manage.py schemamigration --auto yourapp

Во-вторых, создайте миграцию данных:

$ python manage.py datamigration yourapp name_of_migration

В вашей прямой миграции:

for b in orm.B.objects.all():
    for a in b.as.all():
        orm.C.objects.create(a=a, b=b)

В вашей обратной миграции:

for c in orm.C.objects.all():
    c.b.as.add(a)

Наконец, добавьте параметр through к вашему ManyToManyField и сгенерируйте еще одну автоматическую схему миграции:

$ python manage.py schemamigration --auto yourapp
0 голосов
/ 24 октября 2011

Вы также можете попытаться указать параметр db_table для C как 'app_b_a'.Но не уверен, что это сработает.

...