Недавно я перешел с Django 1.6 на 1.7 и начал использовать миграции (я никогда не использовал South).
До версии 1.7 я загружал исходные данные fixture/initial_data.json
файлом, который загружался python manage.py syncdb
командой (при создании базы данных).
Теперь я начал использовать миграции, и такое поведение устарело:
Если приложение использует миграции, автоматическая загрузка фикстур отсутствует. Поскольку для приложений в Django 2.0 потребуется миграция, такое поведение считается устаревшим. Если вы хотите загрузить исходные данные для приложения, рассмотрите возможность переноса данных. ( https://docs.djangoproject.com/en/1.7/howto/initial-data/#automatically-loading-initial-data-fixtures )
В официальной документации нет четкого примера, как это сделать, поэтому мой вопрос:
Как лучше всего импортировать такие исходные данные с помощью миграции данных:
- Напишите код Python с несколькими вызовами
mymodel.create(...)
, - Используйте или напишите функцию Django ( например, вызов
loaddata
) для загрузки данных из файла фикстуры JSON.
Я предпочитаю второй вариант.
Я не хочу использовать South, поскольку Django, похоже, теперь может делать это изначально.
Ответы:
Обновление : см. Комментарий @ GwynBleidD ниже, чтобы узнать о проблемах, которые может вызвать это решение, и см. Ответ @ Rockallite ниже, чтобы узнать о подходе, который более устойчив к будущим изменениям модели.
Предполагая, что у вас есть файл фикстуры в
<yourapp>/fixtures/initial_data.json
Создайте пустую миграцию:
В Django 1.7:
В Django 1.8+ вы можете указать имя:
Отредактируйте файл миграции
<yourapp>/migrations/0002_auto_xxx.py
2.1. Собственная реализация, вдохновленная Django '
loaddata
(начальный ответ):2.2. Более простое решение для
load_fixture
(по предложению @ juliocesar):Полезно, если вы хотите использовать собственный каталог.
2.3. Простейший: вызов
loaddata
сapp_label
загрузят светильники от<yourapp>
«sfixtures
реж автоматически:Если вы не укажете
app_label
, loaddata попытается загрузитьfixture
имя файла из всех каталогов приложений (что вам, вероятно, не нужно).Запустить его
источник
loaddata('loaddata', fixture_filename, app_label='<yourapp>')
также будет идти непосредственно вmodels.py
файлов, которые могут иметь некоторые дополнительные поля или некоторые другие изменения. Если после создания миграции были внесены некоторые изменения, произойдет сбой (поэтому мы даже не сможем создать миграции схемы после этой миграции). Чтобы исправить это, мы можем временно изменить реестр приложений, над которым работает сериализатор, на реестр, предоставленный для функции миграции по первому параметру. Реестр к пути находится по адресуdjango.core.serializers.python.apps
.app registry
без изменения глобальной переменной (что может вызвать проблемы в гипотетическом будущем при параллельной миграции базы данных).Укороченная версия
Вы НЕ должны использовать
loaddata
команду управления непосредственно при миграции данных.Длинная версия
loaddata
утилизируетdjango.core.serializers.python.Deserializer
который использует большинство моделей уточненного десериализовать исторические данные в миграции. Это неправильное поведение.Например, предполагается, что существует миграция данных, в которой используется
loaddata
команда управления для загрузки данных из устройства, и она уже применяется в вашей среде разработки.Позже вы решаете добавить новое обязательное поле в соответствующую модель, поэтому вы делаете это и выполняете новую миграцию для вашей обновленной модели (и, возможно, предоставляете одноразовое значение новому полю при появлении соответствующего
./manage.py makemigrations
запроса).Вы запускаете следующую миграцию, и все хорошо.
Наконец, вы закончили разработку приложения Django и развернули его на рабочем сервере. Пришло время выполнить все миграции с нуля в производственной среде.
Однако перенос данных не выполняется . Это связано с тем, что десериализованная модель из
loaddata
команды, которая представляет текущий код, не может быть сохранена с пустыми данными для нового добавленного вами обязательного поля. В оригинальном приспособлении отсутствуют необходимые данные!Но даже если вы обновите прибор, добавив в него необходимые данные для нового поля, перенос данных все равно не удастся . Когда выполняется миграция данных, следующая миграция, которая добавляет соответствующий столбец в базу данных, еще не применяется. Вы не можете сохранить данные в несуществующий столбец!
Вывод: при миграции данных
loaddata
команда вносит потенциальное несоответствие между моделью и базой данных. Вам определенно НЕ следуетиспользовать его непосредственно при миграции данных.Решение
loaddata
Команда полагается наdjango.core.serializers.python._get_model
функцию для получения соответствующей модели из приспособления, которая вернет самую последнюю версию модели. Нам нужно исправить его, чтобы он получил историческую модель.(Следующий код работает для Django 1.8.x)
источник
objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
страдать от той же проблемы, что иloaddata
? Илиignorenonexistent=True
покрывает все возможные вопросы?ignorenonexistent=True
аргумент имеет два эффекта: 1) он игнорирует модели прибора, которых нет в самых последних определениях моделей, 2) он игнорирует поля модели прибора, которые не входят в в самом последнем соответствующем определении модели. Ни один из них не справляется с ситуацией нового обязательного поля в модели . Так что да, я думаю, что он страдает той же проблемой, что и обычныйloaddata
.natural_key()
, который этот метод, похоже, не поддерживает - я просто заменил значение natural_key на фактический идентификатор модели, на которую указывает ссылка.Вдохновленный некоторыми комментариями (а именно n__o) и тем фактом, что у меня много
initial_data.*
файлов, распределенных по нескольким приложениям, я решил создать приложение Django, которое облегчило бы создание этих миграций данных.Использование Джанго-миграционное приспособление вы можете просто запустить следующую команду управления , и он будет искать через все ваши
INSTALLED_APPS
дляinitial_data.*
файлов и превратить их в миграцию данных.См. Django-migration-fixture для инструкций по установке / использованию.
источник
Чтобы дать вашей базе данных некоторые исходные данные, напишите перенос данных. При миграции данных используйте функцию RunPython для загрузки ваших данных.
Не пишите никаких команд loaddata, так как этот способ устарел.
Ваша миграция данных будет запущена только один раз. Миграции - это упорядоченная последовательность миграций. Когда выполняется миграция 003_xxxx.py, django migrations записывает в базу данных, что это приложение перенесено до этого (003), и будет запускать только следующие миграции.
источник
myModel.create(...)
(или использовать цикл) в функции RunPython?Представленные выше решения, к сожалению, не сработали. Я обнаружил, что каждый раз, когда я меняю свои модели, мне приходится обновлять свои приспособления. В идеале я бы вместо этого написал миграции данных, чтобы аналогичным образом изменять созданные данные и данные, загруженные с помощью приспособлений.
Чтобы облегчить это, я написал быструю функцию, которая будет искать в
fixtures
каталоге текущего приложения и загружать приспособление. Поместите эту функцию в миграцию в ту точку истории модели, которая соответствует полям в миграции.источник
RunPython(load_fixture('badger', 'stoat'))
. gist.github.com/danni/1b2a0078e998ac080111На мой взгляд, светильники немного плохие. Если ваша база данных часто меняется, поддерживать их в актуальном состоянии скоро станет кошмаром. На самом деле, это не только мое мнение, в книге «Два шарика Django» оно объяснено намного лучше.
Вместо этого я напишу файл Python для начальной настройки. Если вам нужно что-то еще, я предлагаю вам взглянуть на Factory boy .
Если вам нужно перенести некоторые данные, вы должны использовать миграцию данных .
Также есть «Запишите свои светильники , используйте фабрики моделей» об использовании светильников.
источник
В Django 2.1 я хотел загрузить некоторые модели (например, названия стран) с исходными данными.
Но я хотел, чтобы это происходило автоматически сразу после выполнения начальных миграций.
Поэтому я подумал, что было бы здорово иметь
sql/
папку внутри каждого приложения, которое требует загрузки исходных данных.Затем в этой
sql/
папке у меня будут.sql
файлы с необходимыми DML для загрузки исходных данных в соответствующие модели, например:Чтобы быть более наглядным, вот как
sql/
будет выглядеть приложение, содержащее папку:Также я нашел несколько случаев, когда мне нужно было, чтобы
sql
скрипты выполнялись в определенном порядке. Поэтому я решил поставить перед именами файлов порядковый номер, как показано на изображении выше.Затем мне понадобился способ
SQLs
автоматически загружать все, что есть в любой папке приложения, путем выполненияpython manage.py migrate
.Итак, я создал другое приложение с именем,
initial_data_migrations
а затем добавил это приложение в списокINSTALLED_APPS
вsettings.py
файле. Затем я создалmigrations
внутри папку и добавил файл с именемrun_sql_scripts.py
( который на самом деле является настраиваемой миграцией ). Как видно на изображении ниже:Я создал
run_sql_scripts.py
так, чтобы он заботился о запуске всехsql
скриптов, доступных в каждом приложении. Этот затем запускается, когда кто-то бежитpython manage.py migrate
. Этот обычайmigration
также добавляет задействованные приложения в качестве зависимостей, таким образом он пытается запускатьsql
операторы только после того, как требуемые приложения выполнили свои0001_initial.py
миграции (мы не хотим пытаться запустить оператор SQL для несуществующей таблицы).Вот источник этого сценария:
Я надеюсь, что кто-то сочтет это полезным, у меня все сработало! Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать.
ПРИМЕЧАНИЕ. Возможно, это не лучшее решение, так как я только начинаю работать с django, но все же хотел поделиться этим «Практическим руководством» со всеми вами, так как я не нашел много информации, пока гуглил об этом.
источник