I have a Django application that must use a database provided by another source. I am not able to change the schema. Everything below was generated by 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')
A ManyToManyField won't work under Family, since the mapping table, Family_spouseref, has multiple foreign keys to Spouseref. Given this schema, what's the most efficient way to accomplish something like this:
fam = Family.objects.get(persistanceid=id)
husbands = fam.husbands.all()
wives = fam.wives.all()
children = fam.children.all()
Update:
As requested... the following functions are what I tried to add within the Family model above.
I tried raw SQL like so:
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])
Which works, but is raw SQL really the best way? I lose out on a lot of the usual object methods this way, it seems like.
When I tried doing it through the ORM, it kept wanting to think that the Family_spouseref table had a column id, which it clearly does not.
Family_spouseref.objects.get(family_persistanceid=self.persistanceid)
Produced:
[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...
I also tried:
Family_spouseref.objects.get(Q(family_persistanceid=self.persistanceid) | Q(husbandrefs_persistanceid__isnull=False))
Which produced the same ID error but did attempt to follow the FK relationship:
[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...
I'm also horrified to see by the debug how often it's calling the same (bad) statement (8 times) vs. the raw SQL, which it calls twice. (Still, twice!)
I really would like to know the official Django way for traversing these tables rather than ignore the ORM entirely and do raw SQL. Thanks.