Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье объясняется, как работает система миграций Django с SQL Server через серверную часть mssql-django, а также документируются известные особые случаи.
Создание и применение миграций
Процесс миграции в Django работает с SQL Server так же, как и с другими базами данных:
Создайте миграции на основе изменений в модели:
python manage.py makemigrations myappПросмотрите созданные файлы миграции в
<app>/migrations/.Примените миграции к базе данных:
python manage.py migrate myappПроверьте состояние миграции:
python manage.py showmigrations myapp
Начальная настройка проекта
При настройке нового проекта Django с SQL Server выполните миграцию для создания встроенных таблиц Django (аутентификация, сеансы, администратор):
python manage.py migrate
Эта команда создает все таблицы, необходимые для приложений, перечисленных в INSTALLED_APPS.
Настраиваемый SQL в миграциях
Используется migrations.RunSQL для выполнения необработанных инструкций SQL во время миграции. Этот подход полезен для создания хранимых процедур, триггеров или других объектов SQL Server.
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("myapp", "0001_initial"),
]
operations = [
migrations.RunSQL(
sql="CREATE INDEX IX_myapp_product_name ON myapp_product (name);",
reverse_sql="DROP INDEX IX_myapp_product_name ON myapp_product;",
),
]
Известные пограничные случаи миграции
Для следующих операций миграции требуются обходные пути при выборе SQL Server.
Изменение автофилда
Изменение типа поля модели с AutoField или на AutoField во время миграции не поддерживается. SQL Server не позволяет добавлять или удалять IDENTITY свойство из существующего столбца.
Обходное решение. Создайте новую модель с нужным типом поля. Перенесите данные из старой таблицы в новую таблицу, а затем удалите старую таблицу.
Переименование поля или модели с ограничениями внешнего ключа
Переименование поля или модели с ограничениями внешнего ключа может завершиться ошибкой. SQL Server требует удаления и повторного восстановления ограничений FK во время операций переименования.
Обходное решение: Используйте migrations.SeparateDatabaseAndState для удаления ограничения внешнего ключа, переименования столбца и повторного создания ограничения, одновременно указав Django обновить состояние модели. В следующем примере внешний ключ product в модели Order переименовывается в item:
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("myapp", "0002_previous"),
]
operations = [
migrations.SeparateDatabaseAndState(
database_operations=[
migrations.RunSQL(
sql="ALTER TABLE myapp_order DROP CONSTRAINT FK_order_product;",
reverse_sql="ALTER TABLE myapp_order ADD CONSTRAINT FK_order_product FOREIGN KEY (product_id) REFERENCES myapp_product(id);",
),
migrations.RunSQL(
sql="EXECUTE sp_rename 'myapp_order.product_id', 'item_id', 'COLUMN';",
reverse_sql="EXECUTE sp_rename 'myapp_order.item_id', 'product_id', 'COLUMN';",
),
migrations.RunSQL(
sql="ALTER TABLE myapp_order ADD CONSTRAINT FK_order_item FOREIGN KEY (item_id) REFERENCES myapp_product(id);",
reverse_sql="ALTER TABLE myapp_order DROP CONSTRAINT FK_order_item;",
),
],
state_operations=[
migrations.RenameField(
model_name="order",
old_name="product",
new_name="item",
),
],
),
]
Найдите фактическое имя ограничения в базе данных перед выполнением этого кода T-SQL. Django генерирует имена ограничений, включающие короткий хэш, поэтому имя в вашей схеме не совпадает с подстановочным именем, показанным здесь.
Миграции Squash
После того как многие миграции накапливаются, их можно разбить на меньшее количество файлов:
python manage.py squashmigrations myapp 0001 0010
Tip
Всегда тестируйте объединённые миграции на чистой базе данных, чтобы убедиться, что в результате создаётся корректная схема.
Созданные столбцы (вычисляемые столбцы)
Серверная часть mssql-django поддерживает GeneratedField Django (Django 5.0 и более поздних версий), которое сопоставляется с вычисляемыми столбцами SQL Server.
Сохраненные (PERSISTED) созданные столбцы
Сохраненный созданный столбец физически записывается на диск и обновляется при изменении исходных столбцов:
from django.db import models
from django.db.models import F
class Product(models.Model):
price = models.DecimalField(max_digits=10, decimal_places=2)
tax_rate = models.DecimalField(max_digits=5, decimal_places=4)
total_price = models.GeneratedField(
expression=F("price") * (1 + F("tax_rate")),
output_field=models.DecimalField(max_digits=10, decimal_places=2),
db_persist=True,
)
Это приводит к следующему: total_price AS ([price] * (1 + [tax_rate])) PERSISTED.
Виртуальные созданные столбцы
Виртуальный созданный столбец вычисляется во время запроса и не использует хранилище:
from django.db import models
from django.db.models import F, Value
from django.db.models.functions import Concat
class Employee(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
full_name = models.GeneratedField(
expression=Concat(F("first_name"), Value(" "), F("last_name")),
output_field=models.CharField(max_length=101),
db_persist=False,
)
Note
SQL Server ограничивает создание индексов для непостоянных вычисляемых столбцов. Используйте, db_persist=True если необходимо индексировать созданный столбец.
Примечания к таблицам и столбцам
Бэкенд mssql-django поддерживает функцию db_comment в Django (в Django 4.2 и более поздних версиях). Примечания хранятся в виде MS_Description расширенных свойств объекта SQL Server.
Примечания к таблицам
class AuditLog(models.Model):
action = models.CharField(max_length=50)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
db_table_comment = "Tracks user actions for compliance auditing."
Комментарии к столбцам
class Measurement(models.Model):
value = models.FloatField(db_comment="Sensor reading in Celsius")
recorded_at = models.DateTimeField(db_comment="UTC timestamp from the data logger")
Комментарии отображаются в SQL Server Management Studio в свойствах столбца/таблицы и через sys.extended_properties.
Составные первичные ключи
Django 5.2 представил CompositePrimaryKey. Серверная mssql-django часть имеет частичную поддержку составных первичных ключей, но некоторые тестовые случаи Django по-прежнему исключены. Проверьте миграции составных ключей и запросы к приложению перед их внедрением в рабочей среде.
-
inspectdbнекорректно создает составные первичные ключи. Определите их вручную после проверки. - Поиск по кортежам не поддерживается. Серверная часть разлагает составные ключевые сравнения в отдельные условия столбца.
- Сравнение кортежей с подзапросами требует Django версии 5.2.4 и выше.
- Некоторые операции миграции по-прежнему имеют известные исключения. Сведения о текущем состоянии см. в разделе "Ограничения" и неподдерживаемые функции в mssql-django .
from django.db import models
from django.db.models import CompositePrimaryKey
class OrderItem(models.Model):
pk = CompositePrimaryKey("order_id", "product_id")
order = models.ForeignKey("Order", on_delete=models.CASCADE)
product = models.ForeignKey("Product", on_delete=models.CASCADE)
quantity = models.IntegerField()
IDENTITY_INSERT обработка
При вставке явных значений в объект AutoField (например, восстановление данных из резервной копии с определенными идентификаторами) серверная часть автоматически упаковывает вставкуSET IDENTITY_INSERT ON / SET IDENTITY_INSERT OFF. Ручное написание SQL-запросов не требуется.
# The backend handles IDENTITY_INSERT automatically
Product.objects.create(id=42, name="Restored Widget", price=9.99)
Note
SQL Server позволяет, чтобы в одном сеансе одновременно только одна таблица имела IDENTITY_INSERT ON. Если вставить явные идентификаторы в несколько таблиц в одном блоке, серверная часть обрабатывает переключатель для каждой atomic() инструкции. Однако одновременные сеансы, также использующие IDENTITY_INSERT в той же таблице, могут конфликтовать.