Django多列外键

Django多列外键,django,django-models,Django,Django Models,可以在另一个模型中定义引用多列的外键吗 例如,一个外键引用product表中的两列索引,SQL语句: FOREIGN KEY (product_category, product_id) REFERENCES product(category, id) 顺便说一句,我已经研究了django.contrib.contenttypes,但我不认为这是这种情况下的完美解决方案。它还不受支持。如果你愿意,这里有一张罚单和可能的处理方法。也许你甚至可以跑步 多列主键支持 关系数据库设计使用一组列作为表的

可以在另一个模型中定义引用多列的外键吗

例如,一个外键引用product表中的两列索引,SQL语句:

FOREIGN KEY (product_category, product_id) REFERENCES product(category, id)

顺便说一句,我已经研究了django.contrib.contenttypes,但我不认为这是这种情况下的完美解决方案。

它还不受支持。如果你愿意,这里有一张罚单和可能的处理方法。也许你甚至可以跑步

多列主键支持

关系数据库设计使用一组列作为表的主键。当此集合包含多个列时,它称为“复合”或“复合”主键。(有关术语的更多信息,请参见​文章讨论了数据库密钥)。 目前,Django模型只支持该集合中的一列,拒绝了许多表的自然主键是多列的设计。Django目前无法使用这些模式;相反,它们必须引入冗余的单列键(“代理”键),迫使应用程序在任何给定实例中对表使用哪个键进行任意或不必要的选择。 本页讨论如何让Django支持这些复合主键。这里有很多细节需要了解,但如果做得好,它将允许数据建模具有更大的灵活性和潜在的简单性

当前状态

当前状态是问题已被接受/分配并正在处理中,并且在​http://github.com/dcramer/django-compositepks. 该实现允许具有复合主键。但是,ForeignKey和RelatedManager中缺少对复合密钥的支持。因此,无法从具有复合主键的模型中导航关系

讨论:

注意-如下所述允许这样做,您可以使用SqlAlchemy替换Django的ORM

外键也可以使用ForeignKeyConstraint对象在表级别定义。此对象可以描述单列或多列外键。多列外键称为复合外键,几乎总是引用具有复合主键的表。下面我们定义了一个具有复合主键的表发票:

invoice = Table('invoice', metadata,
    Column('invoice_id', Integer, primary_key=True),
    Column('ref_num', Integer, primary_key=True),
    Column('description', String(60), nullable=False)
)
然后是具有引用发票的复合外键的表发票\项:

invoice_item = Table('invoice_item', metadata,
    Column('item_id', Integer, primary_key=True),
    Column('item_name', String(60), nullable=False),
    Column('invoice_id', Integer, nullable=False),
    Column('ref_num', Integer, nullable=False),
    ForeignKeyConstraint(['invoice_id', 'ref_num'], ['invoice.invoice_id', 'invoice.ref_num'])
)

是的,这是可能的,但当您使用多列约束(即外键或主键)时,需要创建复合键。 例如:

CREATE TABLE Student (
   S_num INTEGER,
   S_Cate INTEGER,
   S_descr CHAR(200),
   PRIMARY KEY (S_num, S_Cate))

CREATE TABLE sub_Student (
   Ssub_ID INTEGER PRIMARY KEY,
   Sref_num INTEGER,
   Sref_Cate INTEGER,
   sub_descr CHAR(500),
   FOREIGN KEY (Sref_num, Sref_Cate) REFERENCES Student
      (S_num, S_Cate))

无论如何,您可以创建一个“Django装置”,如下所示:

CREATE INDEX product_category_id_id ON product (category_id, id);

为此,必须在模型所在的子文件夹
sql
上创建一个名为
product.sql
的文件。fixture加载在初始syncdb上。

@pratik mandrekar的答案非常好,但我想指出,即使没有适当的多列主键django能够适应跨多列外键的查询。下面是一个基于遗留数据库的示例,该数据库的模式我不允许修改:

鉴于:

来自django.db导入模型的

类别帐户(models.Model):
#总的来说,位置号和乘员号作为帐户的主键。
位置\u no=models.IntegerField()
乘员号=模型。SmallIntegerField()
name=models.CharField(最大长度=100)
类元:
托管=错误
db_表='csracct'
共同唯一=(“位置号”、“占用号”),)
类调用(models.Model):
调用\u id=models.IntegerField(主键=True)
#总的来说,位置号和占用者号充当帐户的外键。
位置\u no=models.IntegerField()
乘员号=模型。SmallIntegerField()
notes=models.TextField()
类元:
托管=错误
db_table='csrcall'
以下是您如何获取名称为“steve”的帐户最近的10次呼叫:

calls=Call.extra(
表=['csracct'],
其中=[
'csracct.location\u no=csrcall.location\u no',
'csracct.ACCOUNT\u no=csrcall.ACCOUNT\u no',
'csracct.name=%s',
],
参数=['steve'],
).order_by('-call_id')[:10]

这不是最优雅的解决方案,但是
extra()
是django的基本queryset工具包的一部分;因此,它与django代码的其余部分配合得很好。请注意我们是如何按顺序排列的,并使用常用的django方法限制/分割查询集。

非常感谢您的回答,它真的很有帮助!:我很想知道答案,但恐怕这不是我所说的Django模型的解决方案。数据库可能有复合外键,但Django似乎还没有提供这种支持。