为什么Djano ORM在简单的外键关系上失败?

时间:2018-05-25 22:38:18

标签: django activerecord django-models

我试图使用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字段更改为父级。

编辑2

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

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

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)>

2 个答案:

答案 0 :(得分:3)

很抱歉听到您在使用Django时遇到问题。随着时间的推移,您可能会喜欢Django ORM以及它如何为您提取所有SQL代码:)

您需要深入了解ORM的工作原理 - 它不是SQL代码的1:1替代品。 t/t6043-merge-rename-directories.sh

在您的具体情况下,您需要创建一个名为Parent的新类,并从ForeignKey类引用该类(通过Categories)(您可能还想重命名CategoriesCategory - 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更多地工作并了解它实际构建的好处时,这是有意义的。

祝你好运!

答案 1 :(得分:0)

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

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

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)>