Я планирую переименовать несколько моделей в существующем проекте Django, где есть много других моделей, имеющих отношение внешнего ключа к моделям, которые я хотел бы переименовать. Я вполне уверен, что это потребует многократных миграций, но я не уверен в точной процедуре.
Допустим, я начинаю со следующих моделей в приложении Django myapp
:
class Foo(models.Model):
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
class AnotherModel(models.Model):
foo = models.ForeignKey(Foo)
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.ForeignKey(Foo)
is_ridonkulous = models.BooleanField()
Я хочу переименовать Foo
модель, потому что название на самом деле не имеет смысла и вызывает путаницу в коде, и это Bar
может привести к более четкому названию.
Из того, что я прочитал в документации по разработке Django, я предполагаю следующую стратегию миграции:
Шаг 1
Изменить models.py
:
class Bar(models.Model): # <-- changed model name
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
class AnotherModel(models.Model):
foo = models.ForeignKey(Bar) # <-- changed relation, but not field name
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.ForeignKey(Bar) # <-- changed relation, but not field name
is_ridonkulous = models.BooleanField()
Обратите внимание, что AnotherModel
имя поля foo
не изменяется, но отношение обновляется для Bar
модели. Я рассуждаю так: мне не следует менять слишком много сразу, и что если я изменю имя этого поля на, bar
я рискую потерять данные в этом столбце.
Шаг 2
Создайте пустую миграцию:
python manage.py makemigrations --empty myapp
Шаг 3
Отредактируйте Migration
класс в файле миграции, созданном на шаге 2, чтобы добавить RenameModel
операцию в список операций:
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RenameModel('Foo', 'Bar')
]
Шаг 4
Применить миграцию:
python manage.py migrate
Шаг 5
Отредактируйте связанные имена полей в models.py
:
class Bar(models.Model):
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
class AnotherModel(models.Model):
bar = models.ForeignKey(Bar) # <-- changed field name
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
bar = models.ForeignKey(Bar) # <-- changed field name
is_ridonkulous = models.BooleanField()
Шаг 6
Создайте еще одну пустую миграцию:
python manage.py makemigrations --empty myapp
Шаг 7
Отредактируйте Migration
класс в файле миграции, созданном на шаге 6, чтобы добавить RenameField
операцию (и) для любых связанных имен полей в список операций:
class Migration(migrations.Migration):
dependencies = [
('myapp', '0002_rename_fields'), # <-- is this okay?
]
operations = [
migrations.RenameField('AnotherModel', 'foo', 'bar'),
migrations.RenameField('YetAnotherModel', 'foo', 'bar')
]
Шаг 8
Примените 2-ю миграцию:
python manage.py migrate
Помимо обновления остальной части кода (представления, формы и т. Д.) Для отображения новых имен переменных, будет ли это в основном работать с новыми функциями миграции?
Кроме того, это кажется много шагов. Можно ли каким-то образом сократить миграционные операции?
Спасибо!
источник
apps.get_model
их. Мне понадобилось много времени, чтобы понять это../manage.py makemigrations myapp
команда спросит вас, переименовали ли вы вашу модель. Например: вы переименовали модель myapp.Foo в Bar? [y / N] Если вы ответите 'y', ваша миграция будет содержатьmigration.RenameModel('Foo', 'Bar')
одинаковые значения для переименованных полей :-)manage.py makemigrations myapp
может по-прежнему не работать: «Возможно, вам придется добавить это вручную, если вы измените название модели и несколько ее полей одновременно; для автоопределителя это будет выглядеть так, как будто вы удалили модель со старым именем и добавили новую с другое имя, и созданная им миграция потеряет все данные в старой таблице. " Django 2.1 Docs Для меня было достаточно создать пустую миграцию, добавить к ней переименование модели, а затем запуститьmakemigrations
как обычно.Сначала я подумал, что метод Fiver работает для меня, потому что миграция работала хорошо до шага 4. Однако неявные изменения ForeignKeyField (Foo) в ForeignKeyField (Bar) не были связаны ни с какими миграциями. Вот почему миграция не удалась, когда я захотел переименовать поля отношений (шаг 5-8). Это может быть связано с тем, что мои «AnotherModel» и «YetAnotherModel» отправляются в других приложениях в моем случае.
Поэтому мне удалось переименовать мои модели и поля отношений, выполнив следующие шаги:
Я адаптировал метод из этого и, в частности, трюк Отранцер.
Так что, как Fiver, скажем, у нас в myapp :
И в myotherapp :
Шаг 1:
Преобразуйте каждый OneToOneField (Foo) или ForeignKeyField (Foo) в IntegerField (). (Это сохранит идентификатор связанного объекта Foo как значение целочисленного поля).
затем
Шаг 2: (Как шаг 2-4 от Fiver)
Изменить название модели
Создайте пустую миграцию:
Затем отредактируйте это как:
В конце концов
Шаг 3:
Преобразуйте ваш IntegerField () обратно в их предыдущий ForeignKeyField или OneToOneField, но с новой моделью бара. (Предыдущее целочисленное поле хранило идентификатор, поэтому django понимает это и восстанавливает соединение, что здорово.)
Затем сделайте:
Очень важно, что на этом этапе вы должны изменять каждую новую миграцию и добавлять зависимость от миграций RenameModel Foo-> Bar. Таким образом, если в myotherapp находятся и AnotherModel, и YetAnotherModel, созданная миграция в myotherapp должна выглядеть следующим образом:
затем
Шаг 4:
В конце концов вы можете переименовать свои поля
а затем сделать автоматическое переименование
(Django должен спросить вас, действительно ли вы переименовали имя модели, скажите «да»)
И это все!
Это работает на Django1.8
источник
IntegerField
. Это отлично сработало для меня и имеет дополнительное преимущество, что они воссоздаются с правильным именем. Естественно, я бы посоветовал проверить все миграции, прежде чем запускать их!ForeignKey
s вIntegerField
s спасло мой день сегодня!Мне нужно было сделать то же самое и следовать. Я изменил модель сразу (шаги 1 и 5 вместе с ответом Fiver). Затем создал миграцию схемы, но отредактировал ее так:
Это сработало отлично. Все мои существующие данные обнаружились, все остальные таблицы ссылались на Бар в порядке.
отсюда: https://hanmir.wordpress.com/2012/08/30/rename-model-django-south-migration/
источник
Для Django 1.10 мне удалось изменить два имени класса модели (включая ForeignKey и с данными), просто запустив Makemigrations, а затем Migrate для приложения. Для шага Makemigrations я должен был подтвердить, что хочу изменить имена таблиц. Миграция изменила названия таблиц без проблем.
Затем я изменил имя поля ForeignKey для соответствия, и Makemigrations снова попросил меня подтвердить, что я хочу изменить имя. Мигрируйте, чем внесли изменения.
Таким образом, я сделал это в два этапа без какого-либо специального редактирования файла. Сначала я получал ошибки, потому что забыл изменить файл admin.py, как упомянуто @wasibigeek.
источник
Я также столкнулся с проблемой, как описал v.thorey, и обнаружил, что его подход очень полезен, но может быть сведен к меньшему количеству шагов, которые фактически являются шагами с 5 по 8, как описал Fiver без шагов с 1 по 4, за исключением того, что шаг 7 необходимо изменить, так как мой ниже шаг 3. Общие шаги следующие:
Шаг 1. Отредактируйте связанные имена полей в models.py
Шаг 2: Создать пустую миграцию
Шаг 3: Отредактируйте класс миграции в файле миграции, созданном на шаге 2
Шаг 4: применить миграцию
Готово
PS я пробовал этот подход на Django 1.9
источник
Я использую Django версии 1.9.4
Я сделал следующие шаги: -
Я только что переименовал модель oldName в NewName Run
python manage.py makemigrations
. Он попросит васDid you rename the appname.oldName model to NewName? [y/N]
выбрать YБеги,
python manage.py migrate
и он попросит тебяСледующие типы контента устарели и должны быть удалены:
Любые объекты, связанные с этими типами содержимого внешним ключом, также будут удалены. Вы уверены, что хотите удалить эти типы контента? Если вы не уверены, ответьте «нет».
Он переименовывает и переносит все существующие данные в новую именованную таблицу для меня.
источник
К сожалению, я обнаружил проблемы (каждый django 1.x) с миграцией переименования, которая оставляет старые имена таблиц в базе данных.
Джанго даже не пробовал ничего на старом столе, просто переименовал свою модель. Та же проблема с внешними ключами и индексами в целом - изменения не отслеживаются должным образом Django.
Самое простое решение (обходной путь):
Реальное решение (простой способ переключать все индексы, ограничения, триггеры, имена и т. Д. В 2 коммитах, а точнее для небольших таблиц):
совершить A:
Bar
. (включая все отношения на схеме)В процессе миграции подготовьте
RunPython
, которые копируют данные из Foo в Bar (включаяid
Foo)коммит Б: (не торопитесь, делайте это, когда мигрирует вся команда)
Foo
дальнейшая очистка:
ошибка в Django:
источник
Просто хотел подтвердить и добавить комментарий Ceasaro. Django 2.0 теперь делает это автоматически.
Я на Django 2.2.1, все что мне нужно было сделать, это переименовать модель и запустить
makemigrations
.Здесь он спрашивает, переименовал ли я определенный класс из
A
вB
, я выбрал yes и запустил migrate, и все, кажется, работает.Примечание. Я не переименовал имя старой модели ни в одном из файлов внутри папки проекта / миграции.
источник
Мне нужно было переименовать пару таблиц. Но Джанго заметил только одно переименование модели. Это произошло потому, что Django перебирает добавленные, а затем удаляемые модели. Для каждой пары он проверяет, принадлежат ли они одному и тому же приложению и имеют ли они одинаковые поля . Только у одной таблицы не было внешних ключей для таблиц, которые нужно переименовывать (внешние ключи содержат имя класса модели, как вы помните). Другими словами, только одна таблица не имела изменений поля. Вот почему это было замечено.
Таким образом, решение состоит в том, чтобы переименовывать одну таблицу за раз, изменяя имя класса модели
models.py
, возможноviews.py
, и делая миграцию. После этого проверьте ваш код на наличие других ссылок (имен классов моделей, связанных имен (запросов), имен переменных). Сделайте миграцию, если это необходимо. Затем, при желании, можно объединить все эти миграции в одну (обязательно скопируйте также и импорт).источник
Я хотел бы написать слова @ceasaro, мои в своем комментарии к этому ответу .
Более новые версии Django могут обнаруживать изменения и спрашивать о том, что было сделано. Я также добавил бы, что Django может смешивать порядок выполнения некоторых команд миграции.
Было бы целесообразно применять небольшие изменения и запуск
makemigrations
иmigrate
если происходит ошибка файл миграция может быть отредактирован.Порядок выполнения некоторых строк можно изменить, чтобы избежать ошибок.
источник
migrations.SeparateDatabaseAndState
может помочь?Если вы используете хорошую IDE, такую как PyCharm, вы можете щелкнуть правой кнопкой мыши на названии модели и выполнить рефакторинг -> переименовать. Это избавит вас от необходимости проходить весь ваш код, который ссылается на модель. Затем запустите makemigrations и мигрируйте. Django 2+ просто подтвердит изменение имени.
источник
Я обновил Django с версии 10 до версии 11:
(
-U
для «апгрейда») и это решило проблему.источник