3

我有一个 Django 应用程序,它必须使用另一个来源提供的数据库。 我无法更改架构。以下所有内容均由 inspectdb 生成:

class Family(models.Model):
    persistanceid = models.BigIntegerField(primary_key=True)

class Spouseref(models.Model):
    persistanceid = models.BigIntegerField(primary_key=True)

class Family_spouseref(models.Model):
    family_persistanceid = models.ForeignKey(Family, db_column='family_persistanceid')
    wiferefs_persistanceid = models.ForeignKey(Spouseref, unique=True, null=True, db_column='wiferefs_persistanceid', blank=True, related_name='wiferefs')
    husbandrefs_persistanceid = models.ForeignKey(Spouseref, unique=True, null=True, db_column='husbandrefs_persistanceid', blank=True, related_name='husbandrefs')
    childrefs_persistanceid = models.ForeignKey(Spouseref, unique=True, null=True, db_column='childrefs_persistanceid', blank=True, related_name='childrefs')

ManyToManyField 在 Family 下不起作用,因为映射表 Family_spouseref 有多个外键到 Spouseref。给定这个模式,完成这样的事情的最有效方法是什么:

fam = Family.objects.get(persistanceid=id)
husbands = fam.husbands.all()
wives = fam.wives.all()
children = fam.children.all()

更新:

根据要求...以下功能是我尝试在上面的家庭模型中添加的。

我尝试了这样的原始 SQL:

    def husbands(self):
        return Spouseref.objects.raw ('SELECT * FROM spouseref WHERE spouseref.persistanceid IN (SELECT husbandrefs_persistanceid FROM family_spouseref WHERE family_persistanceid=%s);', [self.persistanceid])

哪个有效,但原始 SQL 真的是最好的方法吗?看起来,我以这种方式失去了很多常用的对象方法。

当我尝试通过 ORM 执行此操作时,它一直想认为 Family_spouseref 表有一个列 id,而它显然没有。

Family_spouseref.objects.get(family_persistanceid=self.persistanceid)

出品:

[DEBUG] django.db.backends: (0.001) SELECT "family_spouseref"."id", "family_spouseref"."family_persistanceid", "family_spouseref"."wiferefs_persistanceid", "family_spouseref"."husbandrefs_persistanceid", "family_spouseref"."childrefs_persistanceid" FROM "family_spouseref" WHERE "family_spouseref"."family_persistanceid" = 45036  LIMIT 21; args=(45036,)
DatabaseError: column family_spouseref.id does not exist
LINE 1: SELECT "family_spouseref"."id", "family_spouseref"."family_p...

我也试过:

Family_spouseref.objects.get(Q(family_persistanceid=self.persistanceid) | Q(husbandrefs_persistanceid__isnull=False))

这产生了相同的 ID 错误,但确实尝试遵循 FK 关系:

[DEBUG] django.db.backends: (0.000) SELECT "family_spouseref"."id", "family_spouseref"."family_persistanceid", "family_spouseref"."wiferefs_persistanceid", "family_spouseref"."husbandrefs_persistanceid", "family_spouseref"."childrefs_persistanceid" FROM "family_spouseref" LEFT OUTER JOIN "spouseref" ON ("family_spouseref"."husbandrefs_persistanceid" = "spouseref"."persistanceid") WHERE ("family_spouseref"."family_persistanceid" = 45036  OR "spouseref"."persistanceid" IS NOT NULL) LIMIT 21; args=(45036,)
DatabaseError: column family_spouseref.id does not exist
LINE 1: SELECT "family_spouseref"."id", "family_spouseref"."family_p...

通过调试看到它调用相同(错误)语句(8 次)的频率与它调用两次的原始 SQL 相比,我也感到震惊。(仍然,两次!)

我真的很想知道遍历这些表的官方 Django 方式,而不是完全忽略 ORM 并执行原始 SQL。谢谢。

4

1 回答 1

2

您得到的错误是因为 Django 默认将“id”字段设置为主键,如果没有字段将“primary_key=True”声明为参数(例如,您在 Family 模型中这样做)。因此,当您尝试获取模型对象时,您总是会收到如下错误:

DatabaseError: column family_spouseref.id does not exist

首先,给该模型一个主键。我敢打赌它有一个。如果没有,也许你只是想读这个。现在,关于您的效率问题,您可以这样做:

def husbands(self):
    husbandrefs_for_family = Family_spouseref.objects.filter(
        family_persistanceid=self.persistanceid,
    ).values_list('husbandrefs_persistanceid',flat=True)

    return Spouseref.objects.filter(
        persistanceid__in=husbandrefs_for_family,
    )

尽管您似乎正在执行 2 个查询,但您会看到 Django 只执行了一个(嗯,这是一个带有子查询的查询,就像您在 SQL 中所做的那样)。

子查询的values_list部分用于仅带入您想要的表的列。我是您想要的 SLQ 语句的select husbandrefs_persistanceid一部分。

希望能帮助到你!

于 2012-06-10T01:10:04.777 回答