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

У меня есть приложение, которое является в режиме бета-тестирования. Модель этого приложения имеет некоторые классы с явным primary_key. Как следствие использование Django поля и не создает идентификатор автоматически.

class Something(models.Model):
    name = models.CharField(max_length=64, primary_key=True)

Я думаю, что это была плохая идея (см. unicode ошибку при сохранении объекта в django администраторе), и я хотел бы попятиться и иметь идентификатор для каждого класса моей модели.

class Something(models.Model):
    name = models.CharField(max_length=64, db_index=True)

Я внес изменения в свою модель (замените каждый primary_key=True db_index=True), и я хочу переместить базу данных с югом.

К сожалению, миграция перестала работать со следующим сообщением: ValueError: You cannot add a null=False column without a default value.

Я оцениваю различные обходные решения для этой проблемы. Какие-либо предложения?

Спасибо за помощь

34
задан Community 23 May 2017 в 12:10
поделиться

2 ответа

Я только что нашел эту запись блога Ракеша Раджана , которая описывает одно возможное решение:

Override StartSerialization, сделав тип реализующим класс System.Xml.Serialization.IXmlSerializable. Определите, как объект должен быть сериализован в XML в методе WriteXml, и определите, как можно воссоздать объект из последовательности xml в методе ReadXml.

Но это не сработает, поскольку словарь содержит объект , а не определенный тип.

-121--3502270-

Ваш вопрос включает две различные, но связанные концепции. Одна из них - кодировка последовательности (например, Юникод/ASCII). Другой тип данных используется для символьного представления.

Технически можно использовать приложение Юникод с помощью простого char и std:: Последовательности. Для указания последовательности байтов строки можно использовать литералы в шестнадцатеричном (\x5FA) или восьмеричном (\05FA) формате. Обратите внимание, что при таком подходе уже существующие строковые литералы, содержащие символы ASCII, должны оставаться действительными, поскольку Unicode сохраняет коды из ASCII.

Одним из важных точек является необходимость тщательного использования многих функций, связанных со строками. Это происходит потому, что они будут работать с байтами , а не с символами . Например, оператор std:: Последовательность:: [] может дать конкретный байт, который является только частью символа Юникода.

В Visual Studio wchar _ t был выбран в качестве базового типа символов. Так что если вы работаете с библиотеками на базе Microsoft, вам будет легче, если вы будете следовать многим советам, опубликованным другими здесь. Замена char на wchar _ t , использование макросов «T» (если вы хотите сохранить прозрачность между Unicode/не-Unicode) и т. д.

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

-121--2666504-

Согласитесь, ваша модель, вероятно, неверна.

Формальный первичный ключ всегда должен быть суррогатным ключом. Больше никогда ничего. [Сильные слова. Был дизайнером баз данных с 1980-х годов. Важно, что усвоенные знания - это то, что все переменчиво, даже когда пользователи клянутся на могилах своих матерей, что ценность не может быть изменена - это действительно естественный ключ, который можно принять за первичный. Это не первично. Первичными могут быть только суррогаты.]

Вы делаете операцию на открытом сердце. Не связывайтесь с миграцией схем. Вы заменяете схему.

  1. Выгрузите данные в файлы JSON. Используйте для этого собственные внутренние django-admin.py инструменты Джанго. Необходимо создать один файл выгрузки для каждого изменяемого файла и каждой таблицы, зависящей от создаваемого ключа. Отдельные файлы делают это немного проще.

  2. Удалите таблицы, которые требуется изменить, из старой схемы.

    Таблицы, которые зависят от этих таблиц, будут иметь измененные FK; вы можете либо обновить существующие строки или - это может быть проще - удалить и повторно вставить эти строки, также.

  3. Создайте новую схему. При этом создаются только изменяющиеся таблицы.

  4. Запишите сценарии для чтения и перезагрузки данных с новыми ключами. Они короткие и очень похожи. Каждый сценарий будет использовать json.load () для чтения объектов из исходного файла; Затем будут созданы объекты схемы из построенных для вас объектов кортежей JSON. Затем их можно вставить в базу данных.

    У вас два дела.

    • Таблицы с измененными PK будут вставлены и получат новые PK. Они должны быть «каскадированы» к другим таблицам, чтобы гарантировать, что FK другой таблицы также изменяются.

    • Таблицы с FK, которые изменятся, должны будут найти строку в внешней таблице и обновить ссылку на FK.

Альтернатива.

  1. Переименуйте все старые таблицы.

  2. Создайте всю новую схему.

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

  4. Удалите переименованные старые таблицы.

 

65
ответ дан 27 November 2019 в 16:14
поделиться

В настоящее время вы терпите неудачу, потому что добавляете колонку pk, которая нарушает требования NOT NULL и UNIQUE.

Вы должны разделить миграцию на несколько шагов , разделяя миграции по схемам и миграции данных:

  • добавить новый столбец, проиндексированный, но не первичный ключ, со значением по умолчанию (ddl миграция)
  • мигрировать данные: заполните новый столбец правильным значением (миграция данных)
  • пометьте новый столбец первичным ключом, и удалите бывший столбец pk, если он стал ненужным (ddl миграция)
6
ответ дан 27 November 2019 в 16:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: