Как правильно загрузить светильники в Джанго на юг?

Я использую Django 1.5b1 и южную миграцию, и жизнь в целом была великолепной. У меня есть некоторые обновления схемы, которые создают мою базу данных, в том числе таблицу пользователей. Затем я загружаю приспособление для ff.User (моя пользовательская модель пользователя):

def forwards(self, orm):
        from django.core.management import call_command
        fixture_path = "/absolute/path/to/my/fixture/load_initial_users.json"
        call_command("loaddata", fixture_path)

Все работало отлично, пока я не добавил еще одно поле в мой ff.User модель, гораздо дальше по линии миграции. Моя нагрузка на прибор теперь ломается:

DatabaseError: Problem installing fixture 'C:\<redacted>create_users.json':
Could not load ff.User(pk=1): (1054, "Unknown column 'timezone_id' in 'field list'")

Часовой пояс - это поле (ForeignKey), которое я добавил в свою модель пользователя.

Ff.User отличается от того, что находится в базе данных, поэтому Django ORM сдается с ошибкой БД. К сожалению, я не могу указать свою модель в своем приборе как orm['ff.User'], который, кажется, южный способ делать вещи.

Как правильно загружать приборы, используя юг, чтобы они не ломались после модификации моделей, для которых предназначены эти приборы?

6 ответов

Решение

Чтение следующих двух постов помогло мне найти решение:

http://andrewingram.net/2012/dec/common-pitfalls-django-south/

http://news.ycombinator.com/item?id=4872596

В частности, я переписал свои миграции данных, чтобы использовать вывод из 'dumpscript'

Мне нужно было немного изменить полученный скрипт для работы с югом. Вместо того чтобы делать

from ff.models import User

я делаю

User = orm['ff.User']

Это работает точно так, как я хотел. Кроме того, он имеет преимущество, заключающееся в отсутствии жесткого кодирования идентификаторов, как это требуется для приборов.

Я нашел фрагмент Django, который делает эту работу!

https://djangosnippets.org/snippets/2897/

Он загружает данные в соответствии с моделями, замороженными в приборе, а не с фактическим определением модели в коде ваших приложений! Идеально подходит для меня.

Я предложил решение, которое может вас заинтересовать:

/questions/39808426/ne-udalos-zagruzit-svetilniki-s-pomoschyu-south-v-proekte-django/39808445#39808445

По сути, вот как я загружаю свой прибор:

from south.v2 import DataMigration
import json

class Migration(DataMigration):

    def forwards(self, orm):
        json_data=open("path/to/your/fixture.json")
        items = json.load(json_data)
        for item in items:
            # Be carefull, this lazy line won't resolve foreign keys
            obj = orm[item["model"]](**item["fields"])
            obj.save()

        json_data.close()

Самое элегантное решение, которое я нашел, здесь, где ваши модели приложений get_model функция отключена, чтобы вместо этого поставлять модель из поставляемой формы. Затем он устанавливается обратно после применения прибора.

from django.db import models
from django.core.management import call_command

def load_fixture(file_name, orm):
    original_get_model = models.get_model

    def get_model_southern_style(*args):
        try:
            return orm['.'.join(args)]
        except:
            return original_get_model(*args)

    models.get_model = get_model_southern_style
    call_command('loaddata', file_name)
    models.get_model = original_get_model

Вы называете это с load_fixture('my_fixture.json', orm) изнутри вас направляет определение.

Это было неприятной частью использования светильников и для меня. Моим решением было сделать несколько вспомогательных инструментов. Тот, который создает фикстуры путем выборки данных из базы данных и включает в себя историю миграции на юг в фикстурах.

Существует также инструмент для добавления истории миграции на юг к существующим приборам.

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

Первые два можно считать бета-кодом, а третий, пожалуйста, рассматривайте как пригодную для использования альфу, но они уже весьма полезны для меня.

Хотелось бы получить отзывы от других: git@github.com:JivanAmara/django_fixture_tools.git В настоящее время он поддерживает только проекты, использующие git в качестве RCS.

Вообще Юг обрабатывает миграции, используя forwards() а также backwards() функции. В вашем случае вы должны либо:

  • изменить приборы, чтобы они содержали правильные данные, или
  • импортировать фикстуру перед миграцией, которая его нарушает (или в рамках той же миграции, но до изменения схемы),

Во втором случае, перед миграцией, добавляя (или, как в вашем случае, удаляя) столбец, вы должны выполнить миграцию, которая будет явно загружать приборы аналогично этому ( документы):

def forwards(self, orm):
    from django.core.management import call_command
    call_command("loaddata", "create_users.json")

Я считаю, что это самый простой способ выполнить то, что вам нужно. Также убедитесь, что вы не делаете некоторых простых ошибок, таких как попытка импортировать данные с новой структурой перед применением более старых миграций.

Другие вопросы по тегам