#django #django-models #django-mssql
#django #django-модели #django-mssql
Вопрос:
У меня есть модель, которая поддерживается представлением базы данных.
class OrgCode(models.Model):
org_code = models.CharField(db_column=u'code',max_length=15)
org_description = models.CharField(max_length=250)
org_level_num = models.IntegerField()
class Meta:
db_table = u'view_FSS_ORG_PROFILE'
Мне нужно сослаться на это в другой модели
class AssessmentLocation(models.Model):
name = models.CharField(max_length=150)
org = models.ForeignKey(OrgCode)
Я не могу запустить syncdb, потому что ограничения внешнего ключа не могут быть созданы со ссылкой на представление.
u"Foreign key 'FK__main_asse__org__1D114BD1'
references object 'view_FSS_ORG_PROFILE'
which is not a user table.", None, 0, -214
7217900), None)
Command:
CREATE TABLE [main_assessmentlocation] (
[id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY,
[name] nvarchar(150) NOT NULL,
[org] int NOT NULL REFERENCES [view_FSS_ORG_PROFILE] ([id]),
)
Обходной путь состоит в том, чтобы удалить Meta: db_table, указывающий на представление, и позволить sync db создать таблицу OrgCode, затем поместить Meta: db_table обратно после syncdb.
Есть ли способ предотвратить создание ограничений внешнего ключа для определенных моделей или полей?
Обновление: я добавил статический метод к связанной модели, указывающий, что это представление
class OrgCode(models.Model):
org_code = models.CharField(max_length=15)
org_description = models.CharField(max_length=250)
@staticmethod
def is_backend_view():
return True
Затем переопределите DatabaseCreation.sql_for_inline_foreign_key_references в django_mssql creation.py:
def sql_for_inline_foreign_key_references(self, field, known_models, style):
try:
field.rel.to.is_backend_view()
return "", False
except:
return super(DatabaseCreation,self).sql_for_inline_foreign_key_references(field, known_models, style)
Сгенерированный sql из syncdb не учитывает ограничение:
CREATE TABLE [main_assessmentlocation] (
[id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY,
[name] nvarchar(150) NOT NULL,
[org] int, -- NO FK CONSTRAINT ANYMORE --
);
Это действительно связано со взломом django_mssql, поэтому я собираюсь продолжать попытки, возможно, подключение к сигналу django.db.backends.signals.connection_created сработает…
Ответ №1:
в версии разработки django есть db_constraint
поле для ForeignKey
поля модели — docs.
Комментарии:
1. Спасибо! Это то, что мне было нужно, теперь мне просто нужно дождаться, пока это попадет в релиз, и я смогу удалить свой хак.
2.
db_constraint
может безопасно использоваться с версии 1.63. Я сделал это для postgres и получаю запись alter field в файле миграции, но схема базы данных в postgres вообще не меняется.
4. @TimRichardson, я не думаю, что в вашем случае схему БД нужно менять, поскольку Django реализует свои ограничения на уровне БД. Вместо этого попробуйте поискать интересное ограничение в Postgres, например, как описано здесь: dba.stackexchange.com/questions/214863 /…
Ответ №2:
Если вы установите managed=False
(Django docs) в Meta
классе вашей модели, Django не создаст таблицу при запуске syncdb.
class AssessmentLocation(models.Model):
name = models.CharField(max_length=150)
org = models.ForeignKey(OrgCode)
class Meta:
managed = False
В Django есть перехват для предоставления исходных данных sql. Мы можем (ab?) использовать это, чтобы заставить Django создать таблицу сразу после запуска syncdb.
Создайте файл myapp/sql/assessmentlocation.sql
, содержащий инструкцию create table:
CREATE TABLE [main_assessmentlocation] (
[id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY,
[name] nvarchar(150) NOT NULL,
[org] int, -- NO FK CONSTRAINT ANYMORE --
);
Если у вас есть другие модели с внешними ключами к AssessmentLocation
модели, у вас могут возникнуть проблемы, если Django попытается применить ограничение внешнего ключа перед выполнением пользовательского sql для создания таблицы. В противном случае, я думаю, этот подход сработает.
Комментарии:
1. Спасибо! Я изучил это, и это действительно работает. Объектная модель, основанная на представлении, является частью фреймворка, который я создаю для использования другими разработчиками. Я пытаюсь не отклоняться от создания модели syncdb и стандартных документов django.