【问题标题】:Why Django ORM failing on simple foreign key relation?为什么 Django ORM 在简单的外键关系上失败?
【发布时间】:2018-11-05 08:27:13
【问题描述】:

我正在尝试使用 Django 惊人的 ORM 简单地创建 one to many 类别关系模型。

SQL:

create table categories(
    id serial   primary key not null,
    parent_id   int
);
insert into categories values(default,default,default);
update categories set parent_id = 1 where id > 1;

select * from categories;
 id | parent_id
----+-----------
  2 |         1
  3 |         1
  1 |
(3 rows)

Django 惊人的 orm 模型:

class Categories(models.Model):
    id = models.AutoField(primary_key=True)
    parent_id = models.ForeignKey('self')
    class Meta:
        managed = False
        db_table = 'categories'

Django 查询:

Categories.objects.get(id=1)

输出:

django.db.utils.ProgrammingError: column categories.parent_id_id does not exist
LINE 1: SELECT "categories"."id", "categories"."parent_id_id" FROM "...
                                  ^
HINT:  Perhaps you meant to reference the column "categories.parent_id".

为什么它使用parent_id_id 列而不是parent_id 以及如何强制它使用parent_id

编辑

我刚刚将 parent_id 字段更改为 parent。

编辑 2

tatlar 答案不是我的情况,因为我已经有了数据库架构。

因此,在深入研究有关 stackoverflow 的文档和其他问题之后,我得到了结果。该模型包含对每一行的父子类别的引用。它可以被所有类似图形的数据模型(cmets、类别等)继承。

class Categories(models.Model):
    id = models.AutoField(primary_key=True)
    parent = models.ForeignKey('self', on_delete=None, parent_link=True, related_name='children')
    class Meta:
        managed = False
        db_table = 'categories'

获取类别 1 的所有孩子:

from myapp.models import Categories

ch = Categories.objects.get(id=1).children print (ch)
# <QuerySet [<Categories: Categories object (2)>, <Categories: Categories object (3)>]>

获取类别 2 的父级:

from myapp.models import Categories

ch = Categories.objects.get(id=1).parent
print (ch)
# <Categories: Categories object (1)>

【问题讨论】:

  • 你不需要指定parent_id Django 将......只需将字段命名为parent
  • 很高兴您找到了解决方案!为了将来参考,最佳 SO 实践是不要在原始 question 中发布您自己的 SO answer(它不再是问题!)。如果您自己对原始问题的回答(在 Answer 部分中)被认为是正确的并得到 SO 社区的支持,那么它将成为规范的解决方案。

标签: django activerecord django-models


【解决方案1】:

得知您在使用 Django 时遇到问题,我们深感抱歉。随着时间的推移,您可能会喜欢上 Django ORM 以及它如何为您抽象所有 SQL 代码 :)

您需要更深入地了解 ORM 的工作原理——它不是 SQL 代码的 1:1 替代品。 Check out the Model docs.

在您的特定情况下,您需要创建一个名为 Parent 的新类并从您的 Categories 类中引用该类(通过 ForeignKey)(您可能还想将您的 Categories 类重命名为 @ 987654326@ -- ORM 也处理复数)。

试试下面的代码(我已经为你将Categories重命名为Category):

from django.db import models

class Category(models.Model):
    id = models.AutoField(primary_key=True)
    parent = models.ForeignKey(Parent)
    # ... Extra model attributes

    class Meta:
        verbose_name_plural = "categories"


class Parent(models.Model):
    id = models.AutoField(primary_key=True)
    # ... Extra model attributes

然后添加您需要的所有额外属性。这将创建所有数据库表及其关系,而无需您编写任何 SQL。如果您习惯于编写 SQL,那么它一个变化,但是当您更多地使用 ORM 并了解它的实际架构有多好时,它是有意义的。

祝你好运!

【讨论】:

  • 感谢您的帖子,但父类不是需要数据库中的父表吗?如果是这样,我只需要一张桌子,而不是两张。
  • 例如在 SQLAlchemy 中,我可以使用 primary_joins 自己指定任何类型的关系,在 django orm 中有类似的东西吗?
  • Django ORM 将为您创建表和关系——这就是它的工作原理(也是它如此出色的一个原因)。您应该永远需要直接使用 SQL 创建表。我强烈建议您阅读文档 :)
  • 问题在于我已经拥有整个数据库架构,并且我不会更改它,因为 django orm 特定要求...更容易切换到另一个框架哈哈 :)
  • 我自己指定任何类型的关系实际上你可以通过指定self来与模型本身建立关系
【解决方案2】:

tatlar 答案不是我的情况,因为我已经有了数据库架构。

因此,在深入研究有关 stackoverflow 的文档和其他问题之后,我得到了结果。此model 包含对每一行的parentchildren 类别的引用。它可以被所有类似图形的数据模型(cmets、类别等)继承。

class Categories(models.Model):
    id = models.AutoField(primary_key=True)
    parent = models.ForeignKey('self', on_delete=None, parent_link=True, related_name='children')
    class Meta:
        managed = False
        db_table = 'categories'

获取类别 1 的所有孩子:

from myapp.models import Categories

ch = Categories.objects.get(id=1).children
print (ch)
# <QuerySet [<Categories: Categories object (2)>, <Categories: Categories object (3)>]>

获取类别 2 的父级:

from myapp.models import Categories

ch = Categories.objects.get(id=1).parent
print (ch)
# <Categories: Categories object (1)>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-12
    • 2012-06-01
    • 2018-02-24
    • 2011-04-22
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    相关资源
    最近更新 更多