Пришло время углубиться в изменения моделей: как изменять существующие структуры данных и управлять этими изменениями через миграции.
Сегодня мы научимся:
- Как вносить изменения в существующие модели.
- Как создавать миграции для изменений.
- Как применять эти миграции к базе данных.
Изменения в структурах моделей
Когда вы создаете миграции для изменений в моделях, вы фактически инициируете процесс эволюции структуры базы данных. Django заботится о том, чтобы переход между разными версиями модели был максимально безопасным и гладким.
Пример: добавление нового поля
Допустим, у нас есть модель Book, которая изначально выглядит вот так:
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
published_date = models.DateField()
После запуска первоначальной миграции и применения её к базе данных, эту структуру мы уже "запечатали". Однако, через месяц к вам приходит клиент и просит добавить поле ISBN для учёта номеров книг. Вот что нужно сделать:
Открыть файл
models.pyи добавить новое поле.# models.py class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=100) published_date = models.DateField() isbn = models.CharField(max_length=13, null=True, blank=True) # Новое полеСоздать миграцию для этого изменения:
python manage.py makemigrationsПрименить миграцию:
python manage.py migrate
Django проанализирует изменения в модели Book и создаст миграционный файл, добавляющий новое поле isbn в таблицу.
Что произойдет в базе данных?
Django создаст SQL-команду для добавления нового столбца в таблицу Book. Поскольку мы указали null=True и blank=True, база данных не будет требовать обязательного заполнения этого поля для уже существующих записей.
Изменение существующих полей
Теперь предположим, что клиент решил, что 13 символов для ISBN не всегда достаточно, и теперь длина поля должна быть 20 символов. Вот как мы это сделаем:
Откройте
models.pyи измените атрибутmax_lengthдля поляisbn:class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=100) published_date = models.DateField() isbn = models.CharField(max_length=20, null=True, blank=True) # Изменение длиныСоздайте миграцию:
python manage.py makemigrationsПримените изменения:
python manage.py migrate
Django сгенерирует SQL-запрос, который изменяет длину столбца isbn в базе данных.
Удаление полей
Иногда приходится удалять существующие поля. Давайте удалим поле published_date (но помните, что такие изменения могут привести к потере данных!).
Удалите поле из модели:
class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=100) isbn = models.CharField(max_length=20, null=True, blank=True)Создайте миграцию:
python manage.py makemigrationsПримените миграцию:
python manage.py migrate
Django удалит столбец published_date из таблицы Book. Перед этим убедитесь, что вы бэкапите данные из этого столбца, если они вам понадобятся!
Переименование полей
Если нужно сменить имя поля (например, из isbn в isbn_code), используйте всё тот же механизм:
Переименуйте поле в модели:
class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=100) isbn_code = models.CharField(max_length=20, null=True, blank=True) # Новое имяСоздайте миграцию:
python manage.py makemigrationsПримените миграцию:
python manage.py migrate
Сложные изменения: объединение или разделение таблиц
Иногда нужно разделить одну таблицу (модель) на две или, наоборот, объединить несколько моделей в одну. Это сложный процесс, который, как правило, требует ручного вмешательства. Django создаёт миграции, но может также потребоваться написать SQL-запросы вручную.
Как работает Django при создании миграций?
Миграции в Django работают на принципе отслеживания изменений в вашей модели. Когда вы вызываете manage.py makemigrations, Django сравнивает текущую версию моделей с последней миграцией, которая была применена ранее. Затем он генерирует новый миграционный файл на основе этого изменения.
Миграционный файл выглядит как Python-скрипт и обычно находится в папке приложения migrations. Вы можете открыть его и увидеть что-то подобное:
# Пример миграционного файла (auto-generated)
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('books', '0001_initial'), # Зависимость от предыдущей миграции
]
operations = [
migrations.AddField(
model_name='book',
name='isbn',
field=models.CharField(blank=True, max_length=13, null=True),
),
]
Типичные ошибки и как их избежать
Ошибки случаются, когда:
Вы забыли применить миграцию. Если после
makemigrationsвы не выполнитеmigrate, база данных останется в старом состоянии. Обязательно применяйте миграции!Изменения несовместимы. Например, вы решили удалить поле, которое было обязательным (
null=False), — это вызовет проблемы, если в таблице уже есть записи. Обязательно добавляйтеdefaultилиnull=Trueперед такими изменениями.Вы меняете поле, которое связано с ForeignKey. При изменении связанных таблиц используйте осторожные подходы, помня про связанные записи.
Вы случайно изменили уже применённую миграцию. Никогда не редактируйте ранее автоматически созданные миграции. Это может сломать всю последовательность изменений базы данных.
Практическое задание
- Создайте модель
Authorс полямиname(строка длиной до 100 символов) иbirth_date(дата). Проведите миграцию. - Добавьте в модель
Authorполеnationality(строка длиной до 50 символов). Проведите миграцию для этих изменений. - Удалите поле
birth_dateи проведите очередную миграцию. - Взаимодействуйте с моделью через Django shell, запишите несколько авторов в базу и проверьте их поля.
Вуаля, теперь вы готовы смело изменять структуры своих моделей и управлять ими через миграции. Уверен, что ваш клиент оценит гибкость, с которой вы можете отвечать на его изменения требований!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ