Переименование имени класса модели django и соответствующих внешних ключей на юг, без потери данных - PullRequest
6 голосов
/ 20 сентября 2011

Ниже приведена моя модель:

class myUser_Group(models.Model):
    name = models.CharField(max_length=100)


class Channel(models.Model):
    name = models.CharField(max_length=100)
    description = models.CharField(max_length=1000)
    belongs_to_group = models.ManyToManyField(myUser_Group)

class Video(models.Model):
    video_url = models.URLField(max_length=300) 
    belongs_to_channel = models.ManyToManyField(Channel)
    description = models.CharField(max_length=1000)
    tags = TagField()

class UserProfile(models.Model):
       user = models.OneToOneField(User)

class User_History(models.Model):
    date_time = models.DateTimeField()
    user = models.ForeignKey(UserProfile, null=True, blank=True)
    videos_watched = models.ManyToManyField(Video)

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

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

Ответы [ 2 ]

8 голосов
/ 20 сентября 2011

Вы можете сделать это, используя только Юг.

Для этого примера у меня есть приложение под названием usergroups со следующей моделью:

class myUser_Group(models.Model):
    name = models.CharField(max_length=100)

, которое, как я полагаю, уже находится под контролем миграции.с югом.

Измените имя модели:

class MyUserGroup(models.Model):
    name = models.CharField(max_length=100)

и создайте пустую миграцию с юга

$ python manage.py schemamigration usergroups model_name_change --empty

Это создаст файл миграции скелета для вас, чтобыуточните что происходит.Если мы отредактируем его так, чтобы он выглядел следующим образом (этот файл будет в папке app_name / migrations / папка - в данном случае usergroups / migrations /):

import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Change the table name from the old model name to the new model name
        # ADD THIS LINE (using the correct table names)
        db.rename_table('usergroups_myuser_group', 'usergroups_myusergroup')


    def backwards(self, orm):
        # Provide a way to do the migration backwards by renaming the other way
        # ADD THIS LINE (using the correct table names)
        db.rename_table('usergroups_myusergroup', 'usergroups_myuser_group')


    models = {
        'usergroups.myusergroup': {
            'Meta': {'object_name': 'MyUserGroup'},
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
        }
    }

    complete_apps = ['usergroups']

В методе forwards мы переименовываемимя таблицы базы данных, совпадающее с тем, что будет искать ORM django с новым именем модели.Мы отменяем изменение в backwards, чтобы гарантировать, что миграция может быть отменена в случае необходимости.

Запустите миграцию без необходимости импортировать / экспортировать существующие данные:

$ python manage.pymigrate

Единственный оставшийся шаг - обновить внешний ключ и столбцы «многие ко многим» в моделях, которые ссылаются на myUser_Group, и изменить их на ссылку на MyUserGroup.

1 голос
/ 14 января 2012
Решение

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

В вашей модели убедитесь, что у вас есть новое имя таблицы:

class Meta:
        db_table = new_table_name'

Затем, как предложил mmcnickle, создайте пользовательскую миграцию:

python manage.py schemamigration xyz migration_name --empty

Подробнее об этом можно прочитать здесь: https://docs.djangoproject.com/en/dev/ref/models/options/

Теперь с помощью пользовательской миграции также добавьте строку для переименования таблицы вперед и назад:

db.rename_table("old_table_name","new_table_name")

Этого может быть достаточно для переноса и изменения имени таблицы, но если вы ранее использовали имя пользовательской таблицы Class Meta, тогда вам придется сделать немного больше. Поэтому я бы сказал, как правило, просто для безопасности сделайте поиск в вашем файле миграции для «old_table_name» и замените любые записи, которые вы найдете, на новое имя таблицы. Например, если вы ранее использовали имя пользовательской таблицы Class Meta, вы, скорее всего, увидите:

'Meta': {'object_name': 'ModelNameYouWillChangeNext', 'db_table': "u'old_table_name'"},

Так что вам нужно поменять это старое имя таблицы на новое.

Теперь вы можете мигрировать с помощью:

python manage.py migrate xyz

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

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

После этого ваше приложение должно работать нормально. На данный момент ваша задача в значительной степени выполнена, и ваше приложение должно нормально работать с новым именем модели и новым именем таблицы. Единственная проблема, с которой вы столкнетесь при использовании South, это то, что в следующий раз, когда вы создадите миграцию с помощью функции автоопределения, она попытается удалить старую таблицу и создать новую с нуля, поскольку обнаружила имя вашей новой модели. Чтобы это исправить, вам нужно создать еще одну пользовательскую миграцию:

python manage.py schemamigration xyz tell_south_we_changed_the_model_name_for_old_model_name --empty

Приятно то, что здесь вы ничего не делаете, так как вы уже изменили название своей модели, поэтому Саут подхватит это. Просто мигрируйте с помощью «pass» в миграции вперед и назад:

python manage.py migrate xyz

Ничего не сделано, и Юг теперь понимает, что это актуально. Попробуйте:

python manage.py schemamigration xyz --auto

и вы должны увидеть, что ничего не изменилось

...