尝试在 Django 中使用外键列表创建 PostgreSQL 字段

Posted

技术标签:

【中文标题】尝试在 Django 中使用外键列表创建 PostgreSQL 字段【英文标题】:Trying to make a PostgreSQL field with a list of foreign keys in Django 【发布时间】:2016-06-27 17:42:57 【问题描述】:

这是我想要做的: 在 Django 中创建一个模型,它是一个 PostgreSQL 数组(数据库特定类型),其中包含另一个模型的外键。

class Books(models.Model):
    authors = ArrayField(
        models.ForeignKey('my_app.Authors', default=None, null=True, blank=True),
        blank=True,
        default=list()
    )

当我尝试进行迁移时,Django 给了我这个错误:

SystemCheckError: System check identified some issues:
ERRORS:
my_app.Books.authors: (postgres.E002) Base field for array cannot be a related field.

关于如何打败它的任何想法?

【问题讨论】:

您应该为此使用ManyToMany 字段。 【参考方案1】:

您不能创建外键数组。这不是 Django 的限制,而是 PostgreSQL 的“限制”。

原因是外键不是类型it is a constraint on a field。外键数组没有任何意义。

实现这一点的一般方法是使用一个中间表,该表将用作其他两个表之间的链接:

Authors(id, name)
Books(id, title, pub_date)
BookAuthors(id, book_id, author_id)

在上面的例子中,BookAuthors.book_idBooks.id 的外键,BookAuthors.author_idAuthors.id 的外键。因此,BookAuthors 表用于将作者与书籍进行匹配,反之亦然。

Django 用ManyToManyField fields抽象这个中间表:

class Authors(models.Model):
    name = models.CharField(...)

class Books(models.Model):
    title = models.CharField(...)
    pub_date = models.DateField(...)
    authors = models.ManyToManyField('my_app.Authors',
                                     related_name='authored_books')

在幕后,Django 将创建中间表。

然后,您可以使用book.authors.all() 获取一本书的所有作者,或使用author.authored_books.all() 获取作者创作的所有书籍。

【讨论】:

这是有道理的。谢谢!我将只使用这些值而不是作为外键。我有点担心性能,我需要这些相关键的唯一时间是当我选择这个对象本身时。 我认为你应该仍然是多对多的关系。我设置一个整数数组,你可能会遇到很多麻烦。特别是关于数据完整性。我看不到性能问题。 “外键数组没有任何意义。”为什么?对我来说听起来很合理 @MarcosPereira 因为外键是约束(如唯一约束、主键或索引)而不是数据类型。您可以将外键视为规定“列 author_id 的有效值必须是表 User 的任何主键”的规则。 听起来很合理,只是没有实现。【参考方案2】:

你必须使用ManyToManyFieldArrayField不能与其他模型关联。

【讨论】:

以上是关于尝试在 Django 中使用外键列表创建 PostgreSQL 字段的主要内容,如果未能解决你的问题,请参考以下文章

Django Rest API,如何为 2 个模型条目创建 post api,并具有与模型关联的外键

外键 id 无法加载到 Django 模板的下拉列表中

Python:如何在我的 Django 模板中传递外键的值?

POST 请求创建多个对象 AJAX/Django Rest Framework

Unhashable 类型:尝试在 Django 中使用 post_save 动态添加 m2m 关系时出现“列表”错误

视图中的Django外键 - 获取列表中每个用户显示的第一个图像