Переименование приложения с помощью Django и South - PullRequest
31 голосов
/ 31 декабря 2010

Я переименовываю приложение в более подходящее имя.При этом я хочу убедиться, что Юг правильно переносит базу данных (переименовывает таблицы базы данных и изменяет ссылки в django_content_type или south_migrationhistory).Я знаю, как перенести модель в другое приложение , но когда я пытаюсь переименовать само приложение, South не распознает историю миграции должным образом.

Нежелательное решение : При переименовании old_app в new_app я мог бы оставить old_app/migrations без изменений и добавить новые миграции в этот каталог, чтобы перенести базу данных в ссылку new_app.

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

Как лучше переименовать приложение с помощью Django South без потери данных?

Ответы [ 5 ]

43 голосов
/ 14 сентября 2011

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

Если вы хотите избежать потери данных, вы можете сбросить данные старого приложения в файл json.

python manage.py dumpdata old_app --natural --indent=4 1> old_app.json

Обратите внимание на параметр --natural, который заставляет типы контента экспортироваться с их естественными ключами (app_name, model)

Затем вы можете создать небольшую команду, чтобы открыть этот файл json и заменить все ссылки на old_app на new_app.

Как-то так должно работать

class Command(BaseCommand):
    help = u"Rename app in json dump"

    def handle(self, *args, **options):
        try:
            old_app = args[0]
            new_app = args[1]
            filename = args[2]
        except IndexError:
            print u'usage :', __name__.split('.')[-1], 'old_app new_app dumpfile.json'
            return

        try:
            dump_file = open(filename, 'r')
        except IOError:
            print filename, u"doesn't exist"
            return

        objects = json.loads(dump_file.read())
        dump_file.close()

        for obj in objects:
            obj["model"] = obj["model"].replace(old_app, new_app, 1)

            if obj["fields"].has_key("content_type") and (old_app == obj["fields"]["content_type"][0]):
                obj["fields"]["content_type"][0] = new_app

        dump_file = open(filename, 'w')
        dump_file.write(json.dumps(objects, indent=4))
        dump_file.close()

Затем переименуйте приложение, измените имя в INSTALLED_APPS.

Затем вы должны удалить все миграции на юг, восстановить и применить начальную миграцию для нового приложения. Затем выполните команду SQL:

update django_content_type set app_label='new_app' where app_label='old_app'

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

python manage.py loaddata old_app.json

Я сделал что-то похожее в проекте, и, кажется, он работает нормально.

Надеюсь, это поможет

24 голосов
/ 31 мая 2012

Возможно переименовать приложение. В качестве примера проекта см .:

https://github.com/ASKBOT/django-south-app-rename-example

В основном, есть 2 миграции. Сначала таблицы переименовываются с использованием db.rename_table(), а затем обновляются типы контента. Это можно объединить в одну миграцию, проверив if not db.dry_run:. См. Как я могу перенести модель из одного приложения django в новое? для примера.

Для начальной миграции вы можете напрямую переименовать существующие таблицы, если они там есть:

if 'old_app_table_name' in connection.introspection.table_names():
    db.rename_table('old_app_table_name', 'new_app_table_name')
else:
    # Create new app tables directly.

Для таблиц с большим количеством миграций может потребоваться проверить, было ли уже применено старое имя миграции:

from south.models import MigrationHistory
if MigrationHistory.objects.exists(app_name='old_app', migration='0001_initial'):
    return

Наконец, я рекомендую использовать IDE (например, пробную версию PyCharm) для переименования пакета (щелчок правой кнопкой мыши, refactor -> переименовать пакет), потому что он обновит все варианты использования в приложении, включая URLconf, настройки и импорт.

8 голосов
/ 07 августа 2013

После некоторого отключения я придумал это.Должен позаботиться об этом.https://gist.github.com/jamesmfriedman/6168003

1 голос
/ 05 апреля 2016

Отказ от ответственности: Этот ответ предназначен для тех, кто не заботится об истории миграции и уже запутался, переименовав приложение, полностью забыв о миграции (как я сделал).Работал для меня.

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

manage.py schemamigration new_app --initial

Затем, применяя его, подделайте его следующим образом

manage.py migrate new_app 0001 --fake

Не забудьте - подделать его, иначе вы можетев конечном итоге потеря данных

Все дальнейшие миграции будут работать нормально

manage.py migrate new_app 0002

Также вы можете удалить из south_migrationhistory, где app_name = "old_app"

0 голосов
/ 31 декабря 2010

Я бы не стал связываться с именами приложений. Вы обращаетесь к названиям приложений буквально везде. URL-адреса, настройки, другие приложения, шаблоны и т. Д.

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

Что бы это ни стоило, вы всегда можете использовать python import as, чтобы импортировать приложение под другим именем, если вы того пожелаете.

...