Django South - схема и миграция данных одновременно
Разве нельзя сделать что-то вроде следующего с Югом в схеме миграции?
def forwards(self, orm):
## CREATION
# Adding model 'Added'
db.create_table(u'something_added', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('foo', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['something.Foo'])),
('bar', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['something.Bar'])),
))
db.send_create_signal(u'something', ['Added'])
## DATA
# Create Added for every Foo
for f in orm.Foo.objects.all():
self.prev_orm.Added.objects.create(foo=f, bar=f.bar)
## DELETION
# Deleting field 'Foo.bar'
db.delete_column(u'something_foo', 'bar_id')
Увидеть prev_orm
это позволило бы мне получить доступ к f.bar
и делать все в одном. Я считаю, что написать 3 миграции для этого довольно тяжело...
Я знаю, что это не "способ сделать", но, на мой взгляд, это было бы честно намного чище.
Будет ли реальная проблема сделать это между прочим?
3 ответа
Я предполагаю, что ваша цель - убедиться, что удаление не выполняется до переноса данных. Для этого вы можете использовать систему зависимостей на юге.
Вы можете разбить вышесказанное на три части:
001_app1_addition_migration
(в приложении 1)
затем
001_app2_data_migration
(в приложении 2, к которому относится модель Foo)
а потом
002_app1_deletion_migration
(в приложении 1) с чем-то вроде следующего:
class Migration:
depends_on = (
("app2", "001_app2_data_migration"),
)
def forwards(self):
## DELETION
# Deleting field 'Foo.bar'
db.delete_column(u'something_foo', 'bar_id')
Южные миграции используют transaction management
,
При выполнении нескольких миграций одновременно код похож на:
for migration in migrations:
south.db.db.start_transaction()
try:
migration.forwards(migration.orm)
south.db.db.commit_transaction()
except:
south.db.db.rollback_transaction()
raise
так что... хотя не рекомендуется смешивать схемы и миграцию данных, как только вы commit
схема с db.commit_transaction()
таблицы должны быть доступны для использования. Будьте внимательны, чтобы обеспечить backwards()
метод, который делает правильные шаги назад.
Прежде всего, форма, предоставленная Югом, является той, на которую вы мигрируете. Другими словами, он соответствует схеме после завершения миграции. Так что вы можете просто написать orm.Added
вместо self.prev_orm.Added
, Другим следствием этого факта является то, что вы не можете ссылаться foo.bar
поскольку его нет в окончательной схеме.
Способ обойти это (и ответить на ваш вопрос) - пропустить ORM и просто выполнить сырой SQL напрямую.
В вашем случае оператор create, который обращается к удаленной строке, будет выглядеть примерно так:
cursor.execute('SELECT "id", "bar_id" FROM "something_foo"')
for foo_id, bar_id in cursor.fetchall()
orm.Added.ojbects.create(foo_id=foo_id, bar_id=bar_id)