【问题标题】:Django - How to prevent database foreign key constraint creationDjango - 如何防止创建数据库外键约束
【发布时间】:2011-12-24 11:49:03
【问题描述】:

我有一个由数据库视图支持的模型。

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 表,然后在 syncdb 之后将 Meta:db_table 放回。

有没有办法防止为某些模型或字段创建外键约束?

更新:我向相关模型添加了一个静态方法,表明它是一个视图

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

然后覆盖django_mssql creation.py中的DatabaseCreation.sql_for_inline_foreign_key_references:

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)    

syncdb 生成的 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 --
);

它确实涉及破解 django_mssql,所以我将继续尝试,也许挂钩 django.db.backends.signals.connection_created 信号会起作用...

【问题讨论】:

    标签: django django-models django-mssql


    【解决方案1】:

    django 开发版有一个db_constraint 字段用于ForeignKey 模型字段 - docs

    【讨论】:

    • 谢谢!这就是我所需要的,现在我只需要等待它发布,我就可以删除我的 hack。
    • db_constraint 从 1.6 版开始可以安全使用
    • 我已经为 postgres 做了这个,并在迁移文件中获得了一个 alter field 条目,但是 postgres 中的数据库架构根本没有改变。
    • @TimRichardson,我认为您的情况不需要更改数据库架构,因为 Django 在数据库级别实现了其约束。相反,尝试在 Postgres 中搜索有趣的约束,例如如此处所述:dba.stackexchange.com/questions/214863/…
    【解决方案2】:

    如果您在模型的Meta 类中设置managed=False (Django docs),则运行syncdb 时Django 不会创建表。

    class AssessmentLocation(models.Model):
        name = models.CharField(max_length=150)
        org  = models.ForeignKey(OrgCode)
    
        class Meta:
            managed = False
    

    Django 有一个到 provide initial sql data 的钩子。我们可以(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 以创建表之前尝试应用外键约束,您可能会遇到问题。否则,我认为这种方法会奏效。

    【讨论】:

    • 谢谢!我调查了这个,它确实有效。基于视图的相关对象模型是我正在构建的框架的一部分,供其他开发人员使用。我尽量不偏离 syncdb 模型创建和标准 django 文档。
    猜你喜欢
    • 1970-01-01
    • 2020-09-16
    • 2012-01-13
    • 2018-09-30
    • 1970-01-01
    • 2012-04-03
    • 2017-04-20
    • 2011-04-09
    • 2021-08-10
    相关资源
    最近更新 更多