我有一个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()
更新
根据要求......我试图在上面的Family模型中添加以下函数。
我尝试了原始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。感谢。
答案 0 :(得分:2)
你得到的错误是因为Django默认设置了一个“id”字段作为主键,如果没有字段将“primary_key = True”声明为参数(例如你在Family模型中那样做)。因此,当您尝试获取模型对象时,您将始终收到如下错误:
DatabaseError: column family_spouseref.id does not exist
首先,给该模型一个主键。我打赌它有一个。如果不是,也许您只想阅读this。现在,关于你的效率问题,你可以这样做:
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
部分。
希望它有所帮助!