- Проблемы, которые решают миграции
- Настройка проекта Django
- Создание миграций
- Применение миграции
- Смена моделей
- Вывод списка миграций
- Неприменимые миграции
- Именование миграции
- Заключение
- Видео
- Перевод видео
- Ссылка на первоисточник
Проблемы, которые решают миграции
Если вы новичок в Django или в веб-разработке в целом, возможно, вы не знакомы с концепцией миграции баз данных, и может показаться неочевидным, почему это хорошая идея.
Во-первых, давайте быстро определим пару терминов, чтобы убедиться, что все находятся на одной странице. Django разработан для работы с реляционной базой данных, хранящейся в системе управления реляционными базами данных, например PostgreSQL, MySQL или SQLite.
В реляционной базе данных данные организованы в таблицы. Таблица базы данных имеет определенное количество столбцов, но может иметь любое количество строк. Каждый столбец имеет определенный тип данных, например строку определенной максимальной длины или положительное целое число. Описание всех таблиц с их столбцами и соответствующими типами данных называется схемой базы данных.
Все системы баз данных, поддерживаемые Django, используют язык SQL для создания, чтения, обновления и удаления данных в реляционной базе данных. SQL также используется для создания, изменения и удаления самих таблиц базы данных.
Работа напрямую с SQL может быть довольно обременительной, поэтому, чтобы облегчить вашу жизнь, Django поставляется с объектно-реляционным картографом, или сокращенно ORM. ORM отображает реляционную базу данных в мир объектно-ориентированного программирования. Вместо определения таблиц базы данных в SQL вы пишете модели Django на Python. Ваши модели определяют поля базы данных, которые соответствуют столбцам в их таблицах базы данных.
Вот пример того, как класс модели Django сопоставляется с таблицей базы данных:
Модель Django для схемы базы данных
Но простое определение класса модели в файле Python не приводит к волшебному появлению таблицы базы данных из ниоткуда. Создание таблиц базы данных для хранения ваших моделей Django - это задача миграции базы данных. Кроме того, всякий раз, когда вы вносите изменения в свои модели, например, добавляете поле, база данных тоже должна быть изменена. С этим справляется и миграция.
Вот несколько способов, которыми миграции Django облегчают вашу жизнь.
Внесение изменений в базу данных без SQL
Без миграций вам пришлось бы подключиться к своей базе данных и ввести кучу команд SQL или использовать графический инструмент, такой как PHPMyAdmin, для изменения схемы базы данных каждый раз, когда вы хотите изменить определение модели.
В Django миграции в основном написаны на Python, поэтому вам не нужно знать какой-либо SQL, если у вас нет действительно сложных вариантов использования.
Избегайте повторения
Создание модели и последующее написание SQL для создания таблиц базы данных для нее было бы повторяющимся.
Миграции генерируются из ваших моделей, чтобы вы не повторялись.
Обеспечение синхронизации определений модели и схемы базы данных
Обычно у вас есть несколько экземпляров вашей базы данных, например, одна база данных для каждого разработчика в вашей команде, база данных для тестирования и база данных с оперативными данными.
Без миграций вам придется вносить любые изменения схемы в каждую базу данных, и вам нужно будет отслеживать, какие изменения уже были внесены в какую базу данных.
С Django Migrations вы можете легко синхронизировать несколько баз данных с вашими моделями.
Отслеживание изменения схемы базы данных в системе контроля версий
Система контроля версий, такая как Git, отлично подходит для кода, но не настолько для схем баз данных.
Поскольку миграции представляют собой простой Python в Django, вы можете поместить их в систему контроля версий, как и любой другой фрагмент кода.
Надеюсь, теперь вы убедились, что миграции - это полезный и мощный инструмент. Давайте начнем узнавать, как высвободить эту силу.
Настройка проекта Django
В этом руководстве вы будете работать над простым приложением для отслеживания биткойнов в качестве примера проекта. Первый шаг - установить Django. Вот как это сделать в Linux или macOS X с использованием виртуальной среды:
$ python3 -m venv env
$ source env/bin/activate
(env) $ pip install "Django==2.1.*"
...
Successfully installed Django-2.1.3
Теперь вы создали новую виртуальную среду и активировали ее, а также установили Django в этой виртуальной среде.
Обратите внимание, что в Windows вы должны запустить env / bin / activate.bat вместо исходного env / bin / activate, чтобы активировать виртуальную среду.
Для удобства чтения примеры консоли теперь не будут включать в себя часть приглашения (env).
Установив Django, вы можете создать проект, используя следующие команды:
$ django-admin.py startproject bitcoin_tracker
$ cd bitcoin_tracker
$ python manage.py startapp historical_data
Это дает вам простой проект и приложение под названием history_data. Теперь у вас должна быть такая структура каталогов:
bitcoin_tracker/
|
├── bitcoin_tracker/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
|
├── historical_data/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations/
│ │ └── __init__.py
| |
│ ├── models.py
│ ├── tests.py
│ └── views.py
|
└── manage.py
В каталоге bitcoin_tracker есть два подкаталога: bitcoin_tracker для файлов всего проекта и history_data, содержащие файлы для созданного вами приложения.
Теперь, чтобы создать модель, добавьте этот класс в history_data / models.py:
class PriceHistory(models.Model):
date = models.DateTimeField(auto_now_add=True)
price = models.DecimalField(max_digits=7, decimal_places=2)
volume = models.PositiveIntegerField()
Это основная модель для отслеживания цен на биткойны.
Также не забудьте добавить недавно созданное приложение в settings.INSTALLED_APPS. Откройте bitcoin_tracker / settings.py и добавьте исторические_данные в список INSTALLED_APPS, например:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'historical_data',
]
Остальные настройки подходят для этого проекта. В этом руководстве предполагается, что ваш проект настроен на использование базы данных SQLite, которая используется по умолчанию.
Создание миграций
После создания модели первое, что вам нужно сделать, это создать для нее миграцию. Вы можете сделать это с помощью следующей команды:
$ python manage.py makemigrations historical_data
Migrations for 'historical_data':
historical_data/migrations/0001_initial.py
- Create model PriceHistory
Это создает файл миграции, который инструктирует Django о том, как создавать таблицы базы данных для моделей, определенных в вашем приложении. Давайте еще раз посмотрим на дерево каталогов:
bitcoin_tracker/
|
├── bitcoin_tracker/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
|
├── historical_data/
│ ├── migrations/
│ │ ├── 0001_initial.py
│ │ └── __init__.py
| |
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
|
├── db.sqlite3
└── manage.py
Как видите, каталог миграции теперь содержит новый файл: 0001_initial.py.
Вы можете заглянуть в базу данных с помощью команды управления dbshell. В SQLite команда для вывода списка всех таблиц - это просто .tables:
$ python manage.py dbshell
SQLite version 3.19.3 2017-06-27 16:48:08
Enter ".help" for usage hints.
sqlite> .tables
sqlite>
База данных все еще пуста. Это изменится, когда вы примените миграцию. Введите .quit, чтобы выйти из оболочки SQLite.
Применение миграции
Теперь вы создали миграцию, но чтобы действительно внести какие-либо изменения в базу данных, вы должны применить ее с помощью команды управления migrate:
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, historical_data, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying historical_data.0001_initial... OK
Applying sessions.0001_initial... OK
Здесь много всего происходит! Согласно выходным данным, ваша миграция была успешно применена. Но откуда берутся все остальные миграции?
Помните настройку INSTALLED_APPS? Некоторые из других приложений, перечисленных там, также идут с миграциями, и команда управления миграцией применяет миграции для всех установленных приложений по умолчанию.
Взгляните еще раз на базу данных:
$ python manage.py dbshell
SQLite version 3.19.3 2017-06-27 16:48:08
Enter ".help" for usage hints.
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups historical_data_pricehistory
auth_user_user_permissions
sqlite>
Теперь есть несколько таблиц. Их имена дают вам представление об их предназначении. В результате миграции, созданной на предыдущем шаге, была создана таблица history_data_pricehistory. Давайте проверим это с помощью команды .schema:
sqlite> .schema --indent historical_data_pricehistory
CREATE TABLE IF NOT EXISTS "historical_data_pricehistory"(
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"date" datetime NOT NULL,
"price" decimal NOT NULL,
"volume" integer unsigned NOT NULL
);
Команда .schema выводит оператор CREATE, который вы должны выполнить для создания таблицы. Параметр --indent прекрасно его форматирует. Даже если вы не знакомы с синтаксисом SQL, вы можете видеть, что схема таблицы history_data_pricehistory отражает поля модели PriceHistory.
Для каждого поля есть столбец и дополнительный идентификатор столбца для первичного ключа, который Django создает автоматически, если вы явно не укажете первичный ключ в своей модели.
Вот что произойдет, если вы снова запустите команду migrate:
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, historical_data, sessions
Running migrations:
No migrations to apply.
Ничего такого! Django запоминает, какие миграции уже были применены, и не пытается их повторно запустить.
Стоит отметить, что вы также можете ограничить команду управления миграцией одним приложением:
$ python manage.py migrate historical_data
Operations to perform:
Apply all migrations: historical_data
Running migrations:
No migrations to apply.
Как видите, Django теперь применяет миграции только для приложения Historical_data.
Когда вы запускаете миграции в первый раз, рекомендуется применить все миграции, чтобы убедиться, что ваша база данных содержит необходимые таблицы для функций, которые вы можете считать само собой разумеющимися, таких как аутентификация пользователей и сеансы.
Смена моделей
Ваши модели не высечены в камне. Ваши модели будут меняться по мере того, как ваш проект Django приобретает больше возможностей. Вы можете добавлять или удалять поля или изменять их типы и параметры.
Когда вы меняете определение модели, таблицы базы данных, используемые для хранения этих моделей, также должны быть изменены. Если определения вашей модели не соответствуют вашей текущей схеме базы данных, вы, скорее всего, столкнетесь с ошибкой django.db.utils.OperationalError.
Так как же изменить таблицы базы данных? Создав и применив миграцию.
Тестируя свой биткойн-трекер, вы понимаете, что совершили ошибку. Люди продают доли биткойнов, поэтому объем поля должен иметь тип DecimalField, а не PositiveIntegerField.
Давайте изменим модель, чтобы она выглядела так:
class PriceHistory(models.Model):
date = models.DateTimeField(auto_now_add=True)
price = models.DecimalField(max_digits=7, decimal_places=2)
volume = models.DecimalField(max_digits=7, decimal_places=3)
Без миграций вам пришлось бы выяснить синтаксис SQL, чтобы превратить PositiveIntegerField в DecimalField. К счастью, Django сделает это за вас. Просто скажите ему сделать миграцию:
$ python manage.py makemigrations
Migrations for 'historical_data':
historical_data/migrations/0002_auto_20181112_1950.py
- Alter field volume on pricehistory
Теперь вы примените эту миграцию к своей базе данных:
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, historical_data, sessions
Running migrations:
Applying historical_data.0002_auto_20181112_1950... OK
Миграция была применена успешно, поэтому вы можете использовать dbshell, чтобы проверить, повлияли ли изменения:
$ python manage.py dbshell
SQLite version 3.19.3 2017-06-27 16:48:08
Enter ".help" for usage hints.
sqlite> .schema --indent historical_data_pricehistory
CREATE TABLE IF NOT EXISTS "historical_data_pricehistory" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"date" datetime NOT NULL,
"price" decimal NOT NULL,
"volume" decimal NOT NULL
);
Если вы сравните новую схему со схемой, которую вы видели ранее, вы заметите, что тип столбца тома изменился с целого на десятичный, чтобы отразить изменение поля объема в модели с PositiveIntegerField на DecimalField.
Вывод списка миграций
Если вы хотите знать, какие миграции существуют в проекте Django, вам не нужно копаться в каталогах миграции установленных приложений. Вы можете использовать команду showmigrations:
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
historical_data
[X] 0001_initial
[X] 0002_auto_20181112_1950
sessions
[X] 0001_initial
В нем перечислены все приложения в проекте и миграции, связанные с каждым приложением. Кроме того, рядом с уже выполненными миграциями будет отображаться большой крестик. В нашем небольшом примере команда showmigrations не особенно интересна, но она пригодится, когда вы начинаете работать над существующей базой кода или работаете в команде, где вы не единственный, кто добавляет миграции.
Неприменимые миграции
Теперь вы знаете, как вносить изменения в схему базы данных, создавая и применяя миграции. В какой-то момент вам может потребоваться отменить изменения и вернуться к более ранней схеме базы данных, потому что вы:
• Хотите протестировать миграцию, написал коллега
• Поймите, что внесенное вами изменение было плохой идеей
• Параллельная работа над несколькими функциями с разными изменениями базы данных
• Хотите восстановить резервную копию, которая была создана, когда база данных все еще имела более старую схему
К счастью, миграция не должна быть улицей с односторонним движением. Во многих случаях последствия миграции можно отменить, не применяя миграцию. Чтобы отменить миграцию, вы должны вызвать migrate с именем приложения и именем миграции перед миграцией, которую вы хотите отменить.
Если вы хотите отменить миграцию 0002_auto_20181112_1950 в своем приложении исторических_данных, вы должны передать 0001_initial в качестве аргумента команды migrate:
$ python manage.py migrate historical_data 0001_initial
Operations to perform:
Target specific migration: 0001_initial, from historical_data
Running migrations:
Rendering model states... DONE
Unapplying historical_data.0002_auto_20181112_1950... OK
Миграция не была применена, что означает, что изменения в базе данных были отменены. Отмена применения миграции не приводит к удалению файла миграции. В следующий раз, когда вы запустите команду migrate, миграция будет применена снова.
Именование миграции
В приведенном выше примере Django придумал имя для миграции на основе отметки времени - что-то вроде * 0002_auto_20181112_1950. Если вас это не устраивает, вы можете использовать параметр --name, чтобы указать собственное имя (без расширения .py).
Чтобы попробовать это, сначала нужно удалить старую миграцию. Вы уже не применили его, поэтому можете безопасно удалить файл:
$ rm historical_data/migrations/0002_auto_20181112_1950.py
Теперь вы можете воссоздать его с более наглядным именем:
$ ./manage.py makemigrations historical_data --name switch_to_decimals
Это создаст ту же миграцию, что и раньше, за исключением нового имени 0002_switch_to_decimals.
Заключение
В этом руководстве вы довольно много рассмотрели и изучили основы миграции Django.
Напомним, основные шаги по использованию миграции Django выглядят так:
1. Создать или обновить модель
2. RUN ./manage.py makemigrations
3. RUN ./manage.py migrate, чтобы перенести все, или ./manage.py migrate , чтобы перенести отдельное приложение.
4. При необходимости повторите
Это оно! Этот рабочий процесс будет работать большую часть времени, но если что-то пойдет не так, как ожидалось, вы также знаете, как отображать и отменять миграции.
Если вы ранее создавали и изменяли таблицы базы данных с помощью написанного вручную SQL, теперь вы стали намного эффективнее, делегировав эту работу миграции Django.
В следующем руководстве этой серии вы углубитесь в тему и узнаете, как Django Migrations работает изнутри.
Видео
Перевод видео
В этом видео рассматривается новая система миграции в Django 1.7. Эта новая система эффективно заменяет south для обработки миграций, которые мы вносим в вашу базу данных. Мы специально рассмотрим надежный рабочий процесс, который вы можете использовать для создания и применяя миграции и для получения дополнительной информации. Ознакомьтесь с тремя сообщениями в блоге на реальном веб-сайте Python, которые углубляются в миграции, и как они работают.
Это видео просто даст вам основы, необходимые для начала работы, и у меня будут ссылки на эти сообщения в блоге в это описание видео. Поэтому я пошел дальше и настроил базовый проект для работы с ним. Он называется моим проектом контактов, а затем я добавил приложение под названием контакты. И поэтому мы обеспокоены тем, что
модель, поэтому давайте просто проверим это. Чтобы у нас была модель компании, чтобы отслеживать различные компании, которые могут быть для базовой системы CRM продаж. Например, эта модель содержит имя полей о дате добавления и дате изменения. Довольно просто, вы также можете увидеть, что в этом приложении есть папка миграции, в которой будут храниться все наши миграции. Теперь давайте продолжим и создадим нашу первую миграцию. Для этого мы просто запустим команду manage that py make migrations, а затем имя нашего приложение, которое является контактами, и, конечно же, вам нужно добавить приложение контактов в установленные приложения, которые я забыл сделать, поэтому я сделаю это очень быстро. Давайте попробуем это еще раз, так что manage.py, сделайте миграционные контакты, и поэтому вы должны увидеть следующее сообщение здесь и это просто говорит о том, что была создана новая миграция для файла. Миграции приложения контактов с именем 0 0 1 подчеркивание, почему это стандартное соглашение. Это создает модель компании, поэтому теперь нам нужно применить эту миграцию для обновления схемы нашей базы данных, и мы делаем это. Выполнив команду manage py, а затем мигрируем, и, поскольку это новое приложение, мы не только сделали это, но и выполнили миграцию наших контактов. Но он также создал все исходные Django для таблиц. Когда я сделал это, мне нужна была проверка работоспособности, и я просто дважды проверил, чтобы убедиться, что это работает.
Если мы откроем нашу базу данных в сиквеле Lite, браузер сиквела Lite просто перейдите и откройте это в поисковике. Вы можете увидеть здесь нашу таблицу контактов, и в ней есть те же поля, которые мы указали для наших моделей Django. Поэтому, чтобы напомнить, мы создали модель. Затем инициализировали нашу миграцию и, наконец, мы применили ее. Это действительно так, да и на самом деле в большинстве случаев, когда вы добавляете или обновляете модель. Вы будете следовать этому базовому рабочему процессу. Поэтому теперь давайте рассмотрим еще два распространенных сценария внесения изменений в модель и добавления новой модели с внешним ключом. Если мы вернемся назад к моделям, которые py. Давайте внесем простые изменения в эту модель. Давайте добавим новое поле для псевдонима компании, чтобы я мог просто сказать, что псевдоним равен. Модели касаются наших полей, давайте поместим здесь максимальную длину. Пустое поле равно true, если мы продолжим и запустим эту команду, это приведет к миграции. Здесь просто указано, что мы делаем, мы добавляем новое ощущение к модель.
Теперь давайте продолжим и применим при миграции, так что просто управляйте этим py migrate, и это просто применило эту вторую миграцию. Обновив нашу схему базы данных, если мы откроем папку миграции, вы можете увидеть обе наши груды миграции здесь и во втором файле. Где мы обновили модель, вы можете видите, что есть некоторые зависимости. В основном это просто говорит о том, что начальная миграция 0 0 1 начального подчеркивания должна быть выполнена до текущей. Потому что вы не можете вносить обновления в модель, которая еще не существует, а также для получения дополнительной информации об этом по мере того, как копаться глубже в эти файлы миграции. Ознакомьтесь с сопутствующими сообщениями в блоге и, наконец, давайте снова обновим нашу модель и добавим отношения внешнего ключа. Так же давайте продолжим и придерживаемся чего-то базового, поэтому давайте продолжим и добавим следующую модель. Поэтому эта модель предназначена для индивидуального контакта в компании.
Поскольку между компанией и контактом существует прямая связь, он работает для этой же компании. Вы должны выиграть мини-отношения, которые мы установили. Сбросить внешний ключ, который вы можете увидеть здесь, снова связывая их вместе. Давайте продолжим и создадим миграцию. Это просто называется 0 0 3, а затем вы можете применить миграцию круто, так что теперь давайте продолжим и взглянем на файл миграции. Для этот 0 0 3 человека. Вы можете видеть, что эта миграция зависит от того, что вторая миграция произойдет до нее, так что именно это означает снова хорошо, если подчинённые, которых там не было. Эта миграция попытается создать внешний ключ перед таблицей компании была ли даже надежда, что это имеет смысл, снова хорошо. Вы можете проверить сообщение в блоге для получения дополнительной информации, и если вы хотите увидеть более сложные сценарии или, например, как перенести существующие south миграции на новую систему миграции django.
Ссылка на первоисточник
Каждая разработка сайта должна начинаться с технического задания. Техническое задание должно описывать структуру сайта, для кого он предназначен и какой функционал должен на нем присутствовать. . . .
В начале интервью обсуждался вопрос что же такое искусственный интеллект. В современном мире под ИИ понимается всё подряд – от умной колонки Алисы, которая разговаривает, . . .
[…] предыдущий проект Django, в качестве примера создания «системных данных» […]