django загружает данные из прибора после обратной миграции / loaddata использует схему модели, а не схему базы данных - PullRequest
11 голосов
/ 29 марта 2011

Недавно я столкнулся с проблемой при импорте более старых данных, чем моя текущая схема модели.Поток, который я использую и приводит к ошибке:

  • dumpdata с python manage.py dumpdata -> 0002
  • внести некоторые изменения в модель
  • создать миграцию с помощью python manage.py schemamigration имя_приложения --auto -> 0003
  • запустить миграцию
  • играть с базой данных
  • перейти на 0002
  • loaddata сгенерировать SQL, в котором у меня есть текущий(миграция 0003) и вызывает сбой процесса загрузки данных (добавляется поле mpoly)
  File "/usr/local/lib/python2.6/dist-packages/django/db/backends/postgresql_psycopg2/base.py",

строка 44, в результате выполнения возвращают self.cursor.execute (query, args) DatabaseError:столбец "mpoly" отношения "localization_province" не существует LINE 1: ... e "(" id "," name "," slug "," mpoly ") V ...

  • комментируя изменения в models.py, сделанные до 0003, все работает нормально

Можно ли как-то избежать игры с моделями после обратной миграции, если я хочу загрузить данные?

Может быть, я упускаю что-то действительно очевидное ...

PS: я использую South 7.3, Django 1.2.3 и PostgreSQL 8.4 в качестве базы данных.

Ответы [ 3 ]

10 голосов
/ 06 мая 2011

Алекс Видаль предложил хорошее быстрое решение для этого, когда он укусил нас на нашей работе. Для этого нужна библиотека Гари Бернхардта Дингус . Как только у нас будет время, мы вычеркнем зависимость Dingus и отправим запрос на извлечение на юг, но если вы сейчас находитесь в состоянии привязки, это может вывести вас из этого:

from dingus import patch


def loaddata(orm, fixture_name):
    _get_model = lambda model_identifier: orm[model_identifier]

    with patch('django.core.serializers.python._get_model', _get_model):
        from django.core.management import call_command
        call_command("loaddata", fixture_name)

Использование:

from apps.common.utils import loaddata


class Migration(DataMigration):
    def forwards(self, orm):
        loaddata(orm, "initial_fjords.json")

Пока мы тестировали только в Django 1.3. Редактировать : я проверил историю _get_model Джанго, и это должно работать с Джанго 0,95 и выше.

3 голосов
/ 29 марта 2011

Я считаю, что лучше придерживаться любых имеющихся у меня приборов в соответствии с текущей версией кода.Таким образом, при создании миграции 0003 вы выполняете миграцию данных и новый dumpdata, заменяя фиксатор 0002. Когда вы создаете миграцию данных, убедитесь, что вы делаете и вперёд, и назад, таким образом вы закончитес правильными данными при миграции обратно на 0002.

Когда вы выполняете миграцию данных, убедитесь, что вы получаете доступ ко всем моделям через объект orm, в противном случае вы получите ошибки, схожие с тем, что вы уже сделали.опыт работы.

Если вы по какой-то причине хотите запустить код django со старыми данными (версия 0002), то ваши модели должны соответствовать вашей базе данных.Это будет означать проверку соответствующей версии кода, используя любую версию кода, которую вы используете (git, hg, svn ...).Если вы пытаетесь решить проблему «вовремя», вы, вероятно, тоже захотите выполнить ответвление в этой точке.

См. Также комментарии к документации South по поводу приборов

Вотидея, вдохновленная этой ссылкой выше: «Лучше всего написать новую миграцию для загрузки прибора».Как насчет загрузки вашего прибора (который у вас уже есть) из миграции, а не loaddata.Вам все равно нужно создать миграцию данных и использовать объект orm для ручной загрузки данных.Вы можете использовать функции сериализации django , это именно то, что loaddata делает .

В отношении того, почему loaddata использует версию модели, а неверсия базы данных: loaddata - это команда управления django , которая не знает, что делает Юг.Из-за этого он должен оставаться независимым от базы данных и использовать ORM django.Вы всегда можете написать свою собственную команду управления , если вам нужно сделать что-то более конкретное - возможно, вытащить некоторые из версий orm юга или сделать специфичные для базы данных loaddata, которые считывают схему непосредственно из базы данных.Я думаю, что решение в предыдущем параграфе будет намного меньше работы.

2 голосов
/ 05 декабря 2012

Поздно к этой дискуссии, но надеюсь, что это полезно.На самом деле у вас есть два подхода, которые вы можете использовать:

  • Загрузите данные на ранних этапах ваших миграций, а затем используйте миграции данных для их изменения в любое время, когда у вас есть миграция схемы.Преимущество этого заключается в том, что вы проверяете миграцию данных по ходу работы.

  • Загружайте данные в качестве прибора, который всегда будет использовать ваши текущие модели и, следовательно, потребует от вас держать ваши приборы в рабочем состоянии.на сегодняшний день.

В дополнение к описанным выше подходам вы можете загружать данные, используя dumpscript (доступный как часть расширений django-command) для выгрузки вашего фиксатора в python.Оттуда вам нужно отредактировать прибор, чтобы использовать ORM, доступный в рамках миграции, а не ваши модели Django.Обычно это наиболее полезно, если у вас не слишком много данных.

См .: http://south.aeracode.org/attachment/ticket/1010/fixtures.diff

...