Миграционные операции ¶
Файлы миграции состоят из одного или нескольких объектов, Operation
которые декларативно записывают операции, которые должны быть выполнены с базой данных.
Django также использует эти объекты Operation
для перекомпоновки исторического состояния ваших моделей и для расчета изменений, внесенных в модели с момента последней миграции, чтобы вы могли автоматически записывать миграции; вот почему они декларативны, что позволяет Django легко загружать их все в память и выполнять итерацию по ним, не обращаясь к базе данных, чтобы найти, как должен выглядеть проект.
Некоторые Operation
более специализированные объекты предназначены для таких операций, как миграция данных и для расширенного ручного управления базой данных. Вы даже можете написать свои собственные классы, Operation
если хотите учитывать часто вносимые изменения.
Если вам нужен пустой файл миграции для записи ваших собственных объектов Operation
, запустите , но имейте в виду, что ручное добавление операций изменения схемы может испортить детектор автоматического переноса и вызвать неправильный код во время последующих запусков. оф .python manage.py makemigrations --empty nom_application
makemigrations
Все основные операции Django находятся в модуле django.db.migrations.operations
.
Вводный контент см. В тематическом руководстве по миграции .
Схема операций ¶
CreateModel
¶
-
класс
CreateModel
( имя , поля , параметры = Нет , базы = Нет , менеджеры = Нет ) ¶
Создает новую модель в истории проекта и соответствующую таблицу в базе данных.
name
- это имя модели, записанное в файле models.py
.
fields
список двоичных кортежей . Экземпляр поля должен быть несвязанным полем (поэтому просто , а не полем, взятым из другой модели).(nom_champ, instance_champ)
models.CharField(…)
options
- необязательный словарь значений, взятых из класса Meta
модели.
bases
- необязательный список других классов, которые должна унаследовать эта модель; он может содержать как объекты класса, так и строки формата, "nomapp.NomModele"
если вы хотите зависеть от другой модели (поэтому вы наследуете ее историческую версию). В случае отсутствия значение по умолчанию наследуется от стандартной модели models.Model
.
managers
принимает список двоичных кортежей . Первый менеджер в списке будет менеджером по умолчанию данной модели для миграций.(nom_gestionnaire, instance_gestionnaire)
DeleteModel
¶
-
класс
DeleteModel
( имя ) ¶
Удаляет модель из истории проекта и ее таблицы из базы данных.
RenameModel
¶
-
класс
RenameModel
( old_name , new_name ) ¶
Переименовывает шаблон со старого имени на новое.
Вам может потребоваться добавить эту операцию вручную, если вы измените и имя шаблона, и несколько его полей; для автодетектора будет казаться, что старая модель была удалена, а новая модель была добавлена с другим именем, что приведет к потере всех данных из старой таблицы при созданной миграции.
AlterModelTable
¶
-
класс
AlterModelTable
( название , таблица ) ¶
Изменяет имя таблицы модели (параметр db_table
внутреннего класса Meta
).
AlterUniqueTogether
¶
-
класс
AlterUniqueTogether
( имя , уникальные_всего ) ¶
Изменяет набор ограничений уникальности модели (параметр unique_together
внутреннего класса Meta
).
AlterIndexTogether
¶
-
класс
AlterIndexTogether
( имя , индекс_всего ) ¶
Изменяет набор настраиваемых индексов модели (параметр index_together
внутреннего класса Meta
).
AlterOrderWithRespectTo
¶
-
class
AlterOrderWithRespectTo
( name , order_with_respect_to ) ¶
Создает или удаляет _order
необходимый столбец для параметра order_with_respect_to
внутреннего класса Meta
.
AlterModelOptions
¶
-
класс
AlterModelOptions
( имя , параметры ) ¶
Сохраняет изменения в различных параметрах модели (атрибутах класса Meta
модели) как permissions
или verbose_name
. Не влияет на базу данных, но сохраняет эти изменения для использования экземплярами RunPython
. options
должен быть словарь, сопоставляющий имена параметров с их значениями.
AlterModelManagers
¶
-
класс
AlterModelManagers
( имя , менеджеры ) ¶
Изменяет обработчики, доступные во время миграции.
AddField
¶
-
класс
AddField
( имя_модели , имя , поле , preserve_default = True ) ¶
Добавляет поле в модель. model_name
это имя шаблона, name
это имя поля, и field
является Field
несвязанным экземпляр поля (что бы вы положили в объявлении поля в models.py
, например models.IntegerField(null=True)
).
Параметр preserve_default
указывает, является ли значение поля по умолчанию постоянным и должно быть включено в состояние проекта ( True
) или оно только временное и предназначено только для миграции ( False
), обычно потому, что миграция добавляет ненулевое поле в таблицу и требуется значение по умолчанию для заполнения существующих строк. Это не влияет на поведение установки значений по умолчанию в самой базе данных, поскольку Django никогда не устанавливает значения по умолчанию для базы данных и всегда применяет их на уровне кода Django ORM.
Предупреждение
В более старых базах данных добавление поля со значением по умолчанию может привести к полной перезаписи таблицы. Это происходит даже для полей с допустимым нулевым значением и может повлиять на производительность. Чтобы этого не произошло, нужно предпринять следующие шаги.
- Добавьте поле с пустым значением, разрешенным без значения по умолчанию, и выполните команду
makemigrations
. Это должно вызвать миграцию, содержащую операциюAddField
. - Добавьте в свое поле значение по умолчанию и выполните команду
makemigrations
. Это должно вызвать миграцию, содержащую операциюAlterField
.
RemoveField
¶
-
класс
RemoveField
( имя_модели , имя ) ¶
Удаляет поле из модели.
Имейте в виду, что в обратном случае это фактически добавление поля в модель. Операция является обратимой (за исключением любой потери данных, которая необратима), если поле допускает значение NULL или если оно имеет значение по умолчанию, которое можно использовать для заполнения воссозданного столбца. Если поле не допускает значения NULL и не имеет значения по умолчанию, операция необратима.
AlterField
¶
-
класс
AlterField
( имя_модели , имя , поле , preserve_default = True ) ¶
Изменяет определение поля, в том числе изменения в его тип, атрибуты null
, unique
, db_column
или другие атрибуты поля.
Параметр preserve_default
указывает, является ли значение поля по умолчанию постоянным и должно ли оно быть включено в состояние проекта ( True
) или оно только временное и предназначено только для миграции ( False
), обычно потому, что миграция изменяет пустое поле на ненулевое поле в таблицу, и ему необходимо значение по умолчанию для заполнения существующих строк. Это не влияет на поведение установки значений по умолчанию в самой базе данных, поскольку Django никогда не устанавливает значения по умолчанию для базы данных и всегда применяет их на уровне кода Django ORM.
Обратите внимание, что не всегда возможно внести все изменения, в том числе в зависимости от базы данных. Например, невозможно преобразовать поле текстового типа, как models.TextField()
в поле числового типа, как models.IntegerField()
в большинстве баз данных.
RenameField
¶
-
класс
RenameField
( model_name , old_name , new_name ) ¶
Изменяет имя поля (и, если оно db_column
не определено, имя столбца).
AddIndex
¶
-
class
AddIndex
( имя_модели , индекс ) ¶
Создает индекс в таблице базы данных для модели model_name
. index
является экземпляром класса Index
.
RemoveIndex
¶
-
класс
RemoveIndex
( имя_модели , имя ) ¶
Удаляет именованный индекс name
из модели с именем model_name
.
Специальные операции ¶
RunSQL
¶
-
класс
RunSQL
( SQL , reverse_sql = None , state_operations = None , намеки = нет , elidable = False ) ¶
Позволяет выполнять произвольный код SQL в базе данных, что полезно для более продвинутых функций механизмов базы данных, которые Django не поддерживает напрямую.
sql
, и, reverse_sql
если указан, должны быть строками SQL для выполнения в базе данных. Для большинства механизмов баз данных (всех, кроме PostgreSQL) Django разделяет код SQL на отдельные операторы перед их выполнением.
Предупреждение
В PostgreSQL и SQLite используйте операторы SQL BEGIN
или COMMIT
только в неатомарных миграциях , чтобы не нарушать состояние транзакции Django.
Вы также можете передать список строк или двоичных кортежей. Эта последняя опция используется для передачи запросов и параметров по тому же принципу, что и для cursor.execute () . Эти три операции эквивалентны:
migrations.RunSQL("INSERT INTO musician (name) VALUES ('Reinhardt');")
migrations.RunSQL([("INSERT INTO musician (name) VALUES ('Reinhardt');", None)])
migrations.RunSQL([("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])])
Если вы хотите включить в запрос буквальные знаки процента, вы должны удвоить их, если передаете параметры.
Запросы reverse_sql
выполняются, когда миграция отменена. Они должны отменять то, что делают запросы sql
. Например, чтобы отменить указанную выше вставку с удалением:
migrations.RunSQL(
sql=[("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])],
reverse_sql=[("DELETE FROM musician where name=%s;", ['Reinhardt'])],
)
Если reverse_sql
есть None
(по умолчанию), операция RunSQL
необратима.
Параметр state_operations
используется для предоставления операций, эквивалентных коду SQL с точки зрения статуса проекта. Например, если вы создаете столбец вручную, вы должны передать список, содержащий операцию, AddField
чтобы автодетектор мог поддерживать актуальное состояние модели. В противном случае при следующем запуске makemigrations
он не увидит никаких операций, добавляющих это поле, и, следовательно, попытается создать его заново. Например :
migrations.RunSQL(
"ALTER TABLE musician ADD COLUMN name varchar(255) NOT NULL;",
state_operations=[
migrations.AddField(
'musician',
'name',
models.CharField(max_length=255),
),
],
)
Необязательный параметр hints
будет передан как **hints
метод allow_migrate()
маршрутизаторам баз данных, чтобы помочь им принимать решения о маршрутизации. См. Подсказки для получения дополнительной информации о подсказках базы данных.
Необязательный параметр elidable
определяет, будет ли операция подавлена (пропущена) при объединении миграций .
-
RunSQL.
noop
¶ Передайте атрибут
RunSQL.noop
вsql
или,reverse_sql
если вы хотите, чтобы операция ничего не делала в заданном направлении. Это особенно полезно для того, чтобы сделать операцию обратимой.
RunPython
¶
-
Класс
RunPython
( код , reverse_code = None , атомные = None , намеки = нет , elidable = False ) ¶
Запускает собственный код Python в историческом контексте. code
(и reverse_code
если он указан) должны быть исполняемыми объектами, принимающими два параметра; первый - это экземпляр, django.apps.registry.Apps
содержащий историзованные модели, которые соответствуют положению операции в истории проекта, а второй - экземпляр SchemaEditor
.
Параметр reverse_code
вызывается при обращении миграций. Этот исполняемый объект должен отменить то, что было сделано исполняемым объектом, code
чтобы эта миграция была обратимой. Если reverse_code
есть None
(по умолчанию), операция RunPython
необратима.
Необязательный параметр hints
будет передан как **hints
метод allow_migrate()
маршрутизаторам базы данных, чтобы помочь им принять решение о маршрутизации. См. Подсказки для получения дополнительной информации о подсказках базы данных.
Необязательный параметр elidable
определяет, будет ли операция подавлена (пропущена) при объединении миграций .
Рекомендуется написать код как отдельную функцию поверх класса Migration
в файле миграции и передать его в RunPython
. Вот пример использования RunPython
для создания некоторых исходных объектов модели Country
:
from django.db import migrations
def forwards_func(apps, schema_editor):
# We get the model from the versioned app registry;
# if we directly import it, it'll be the wrong version
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).bulk_create([
Country(name="USA", code="us"),
Country(name="France", code="fr"),
])
def reverse_func(apps, schema_editor):
# forwards_func() creates two Country instances,
# so reverse_func() should delete them.
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).filter(name="USA", code="us").delete()
Country.objects.using(db_alias).filter(name="France", code="fr").delete()
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(forwards_func, reverse_func),
]
Обычно это операция, которая используется для создания миграции данных , для инициирования пользовательских обновлений и изменений данных или для любой другой операции, которая требует использования ORM или кода Python. ,
Как RunSQL
и в случае, если вы вносите здесь изменения в схему, будьте осторожны, чтобы сделать это за пределами системы моделей Django (например, с триггерами) или используйте SeparateDatabaseAndState
для вставки операций, отражающих ваши изменения в состоянии. моделей. В противном случае версионный ORM и автодетектор могут работать некорректно.
По умолчанию RunPython
будет выполнять свое содержимое внутри транзакции для баз данных, которые не поддерживают транзакции DDL (операторы изменения схемы), например MySQL или Oracle. В принципе это работает нормально, но может вызвать сбой, если вы попытаетесь использовать объект, schema_editor
предоставляемый этими движками; в этом случае переходите atomic=False
к операции RunPython
.
Для баз данных, поддерживающих транзакции схемы DDL (SQLite и PostgreSQL), никакие транзакции не добавляются автоматически для операций RunPython
за пределами транзакций, созданных для каждой миграции. Так, например, с PostgreSQL, вам следует избегать объединения изменений схемы с операциями RunPython
в рамках одной миграции, чтобы избежать таких ошибок .OperationalError: cannot ALTER TABLE "mytable" because it has pending trigger events
Если ваша база данных отличается, и вы не уверены, поддерживает ли она транзакции DDL, проверьте атрибут django.db.connection.features.can_rollback_ddl
.
Если операция RunPython
является частью неатомарной миграции , операция будет выполняться в транзакции, только если atomic=True
она передана в операцию RunPython
.
Предупреждение
RunPython
не меняет волшебным образом подключение моделей для вас; любой вызываемый вами метод шаблона будет направлен в базу данных по умолчанию, если вы не укажете им псевдоним базы данных для использования (доступен в schema_editor.connection.alias
, где schema_editor
- второй параметр, полученный вашей функцией).
-
static
RunPython.
noop
() ¶ Передайте метод ,
RunSQL.noop
чтобыcode
илиreverse_code
когда вы хотите, чтобы операция не делать ничего в данном направлении. Это особенно полезно для того, чтобы сделать операцию обратимой.
SeparateDatabaseAndState
¶
-
class
SeparateDatabaseAndState
( database_operations = None , state_operations = None ) ¶
Узкоспециализированная операция, позволяющая смешивать операции, связанные с аспектами модификации схемы базы данных, с операциями изменения состояния (в связи с автодетектором).
Он принимает два списка операций. На вопрос , чтобы применить изменения состояния, он использует список state_operations
(это обобщенный вариант параметра state_operations
в RunSQL
). Когда его просят применить изменения базы данных, он использует список database_operations
.
Если текущее состояние базы данных и представление Django об этом состоянии различаются, это может нарушить систему миграции или даже привести к потере данных. Стоит быть осторожным и внимательно следить за базой данных и государственными операциями. Вы можете использовать sqlmigrate
и dbshell
для проверки операций с базой данных. Вы можете использовать makemigrations
, особенно с опцией --dry-run
, для проверки состояния операций.
Чтобы увидеть пример использования SeparateDatabaseAndState
, см. Раздел Изменение ManyToManyField для использования промежуточного шаблона .
Написание пользовательских операций ¶
Операции имеют относительно простой API и спроектированы таким образом, чтобы вы могли легко писать подклассы, дополняющие те, которые предоставляет Django. Базовая структура a Operation
выглядит так:
from django.db.migrations.operations.base import Operation
class MyCustomOperation(Operation):
# If this is False, it means that this operation will be ignored by
# sqlmigrate; if true, it will be run and the SQL collected for its output.
reduces_to_sql = False
# If this is False, Django will refuse to reverse past this operation.
reversible = False
def __init__(self, arg1, arg2):
# Operations are usually instantiated with arguments in migration
# files. Store the values of them on self for later use.
pass
def state_forwards(self, app_label, state):
# The Operation should take the 'state' parameter (an instance of
# django.db.migrations.state.ProjectState) and mutate it to match
# any schema changes that have occurred.
pass
def database_forwards(self, app_label, schema_editor, from_state, to_state):
# The Operation should use schema_editor to apply any changes it
# wants to make to the database.
pass
def database_backwards(self, app_label, schema_editor, from_state, to_state):
# If reversible is True, this is called when the operation is reversed.
pass
def describe(self):
# This is used to describe what the operation does in console output.
return "Custom Operation"
Вы можете взять эту модель и расширить ее, хотя мы предлагаем взглянуть на операции, предоставляемые Django в django.db.migrations.operations
. Они охватывают большую часть примеров использования ProjectState
полувнутренних аспектов миграционной системы, таких как механизмы, используемые для получения историзованных моделей, а также ModelState
мотивы, использованные для развития моделей, историзуемых в state_forwards()
.
Несколько замечаний:
ProjectState
Чтобы писать миграции, вам не нужно много знать об этом ; вам просто нужно знать, что у него есть свойствоapps
, предоставляющее доступ к реестру приложений (по которому вы можете позвонитьget_model
).database_forwards
иdatabase_backwards
оба получают два состояния; они представляют собой отличие от того, что использовалосьstate_forwards
бы в этом методе , но переданы вам для удобства и ради скорости.Если вы хотите управлять классами или экземплярами моделей с помощью параметра
from_state
вdatabase_forwards()
илиdatabase_backwards()
, вы должны создать состояния модели с помощью методаclear_delayed_apps_cache()
, чтобы сделать связанные модели доступными:def database_forwards(self, app_label, schema_editor, from_state, to_state): # This operation should have access to all models. Ensure that all models are # reloaded in case any are delayed. from_state.clear_delayed_apps_cache() ...
to_state
в методеdatabase_backwards
- старшее состояние ; то есть тот, который будет представлять текущее состояние, когда миграция завершит работу по отмене.Вы можете найти реализации
references_model
в операциях, предоставляемых Django; это часть кода автоопределения и не играет роли для пользовательских операций.
Предупреждение
По соображениям производительности экземпляры Field
в ModelState.fields
повторно используются от одной миграции к другой. Никогда не трогайте атрибуты этих экземпляров. Если вам нужно развить поле state_forwards()
, вы должны удалить старый экземпляр ModelState.fields
и добавить на его место новый. Тот же принцип применяется к экземплярам Manager
в ModelState.managers
.
В качестве примера давайте создадим операцию, которая загружает расширения PostgreSQL (которые содержат некоторые из наиболее интересных функций PostgreSQL. Поскольку нет изменения состояния модели, все, что она делает, это выполнить команду:
from django.db.migrations.operations.base import Operation
class LoadExtension(Operation):
reversible = True
def __init__(self, name):
self.name = name
def state_forwards(self, app_label, state):
pass
def database_forwards(self, app_label, schema_editor, from_state, to_state):
schema_editor.execute("CREATE EXTENSION IF NOT EXISTS %s" % self.name)
def database_backwards(self, app_label, schema_editor, from_state, to_state):
schema_editor.execute("DROP EXTENSION %s" % self.name)
def describe(self):
return "Creates extension %s" % self.name