Django - Как предотвратить создание ограничений внешнего ключа базы данных - PullRequest
9 голосов
/ 08 ноября 2011

У меня есть модель, поддерживаемая представлением базы данных.

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 ...

Ответы [ 2 ]

15 голосов
/ 03 мая 2013

django-версия разработки имеет поле db_constraint для ForeignKey поля модели - документы .

4 голосов
/ 09 ноября 2011

Если вы установите 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 [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 для создания таблицы.В противном случае, я думаю, что этот подход будет работать.

...