【问题标题】:How to set 2 attributes to primary key together in Django?如何在 Django 中将 2 个属性一起设置为主键?
【发布时间】:2020-04-20 10:31:17
【问题描述】:

我在 Django 中有一个模型:

 class Subject(models.Model):
    level = models.CharField(max_length=50)
    subject_name = models.CharField(max_length=50)
    teacher_name = models.ForeignKey(Teacher, on_delete=models.CASCADE)
    total_seats = models.IntegerField()
    subject_details = models.CharField(max_length=50)

对于Subject 表,我希望levelsubject_name 一起作为主键。事实上,我不希望任何其他对象具有相同的名称和级别。我知道我可以使用unique_together,但我在哪里提到primary_key = True

【问题讨论】:

  • 你没有。在 Django 中,可以将多个属性一起用作主键。它已被多次请求,但不知何故显然不容易做到。
  • 你知道我能做些什么吗?
  • 为什么要设为主键?您可以使用id = AutoField()。有一些库,但这些库都很旧(github.com/simone/django-compositekey 自 2015 年以来未更新)。主要问题不是数据库级别的主键,而是很多 Django 框架和构建在 Django 之上的包都假设some_subject.pk 将是一个奇异值。

标签: django django-models


【解决方案1】:

没有。 Django 不适用于复合主键。这是在documentation 中指定的:

每个模型都需要恰好一个字段具有primary_key=True(显式声明或自动添加)。

FAQ section 中还继续:

Django 模型是否支持多列主键?

。仅支持单列主键。

但这在实践中不是问题,因为没有什么可以阻止 您可以添加其他约束(使用 unique_together 模型 选项或直接在数据库中创建约束),以及 在该级别强制执行唯一性。单列主键是 管理界面等工作所需的东西;例如,你需要 用于指定要编辑或删除的对象的单个值。

这是一个经常被要求的功能(例如,参见Django ticket),但它没有实现。这可能会很麻烦,首先需要更新很多现有的 Django 工具(例如,JOINs 应该使用两个键来完成,FOREIGN KEYs 应该导致构造两个或多个字段, ETC。)。但另一个可能更严重的问题可能是构建在 Django 之上的大量包假设主键不是复合的。因此,它会破坏 Django“生态系统”中的许多包。

有一些像django-compositekey [GitHub] 这样的包旨在实现这一点。但最后一次更新是在 2014 年 10 月。

不将其设为主键本身不是问题。事实上,Django 的GenericForeignKey [Django-doc] 仅在主键都是相同类型的情况下才有效。所以使用unique_together 就足够了。通常这也会在数据库端生成一个UNIQUE INDEX

【讨论】:

  • 那么我应该只添加一个带有 unique_together 的元类而不弄乱主键吗?
  • @iscream:我认为这确实是最好的,是的。
【解决方案2】:

我认为您希望这两个字段由数据库索引,因为主键的主要原因是使字段唯一并由 DBMS 索引,因此您可以在 Meta 类中设置字段 unique_together 并在字段中设置 db_index=True参数。

【讨论】:

  • db_index=True 有什么作用?我需要把它放在两个属性上吗?
  • 在数据库表中索引您的字段,是的,您可以在两个字段上使用它。
猜你喜欢
  • 2012-03-29
  • 1970-01-01
  • 2013-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
  • 2021-03-04
相关资源
最近更新 更多