我有一个系统,其中有一个与一个模型的数量有多对一的关系(比如1a - >多个b),并且许多模型与另一个模型具有一对一的关系(比如说1b - > 1 c)。如此画出:
/--- b1 --- c1
/
a ---- b2 --- c2
\
\--- b3 --- c3
我决定创建一个方法,收集与c
对应的所有a
。
鉴于模型系统具有与我相同的结构,我可以提出的最佳方法显示在方法中:Person.find_important_treats()
。
是否有更好的方法不涉及如此多的数据库调用?
from django.db import models
class Person(models.Model):
""" The 'a' from my above example """
def find_important_treats(self):
return (pet.treat for pet in self.pets)
class Pet(models.Model):
""" The 'b' from my above example """
owner = models.ForeignKey(
to=Person,
related_name='pets'
)
favourite_treat = models.ForeignKey(
to=Treat,
)
class Treat(models.Model):
""" The 'c' from my above example """
pass
答案 0 :(得分:4)
根据您的使用情况,我建议使用两种几乎相似的解决方案:
class Person(models.Model):
""" The 'a' from my above example """
@property
def iter_important_treats(self):
return (pet.treat_id for pet in self.pets.all()) # will use the cached objects if they exist
person = Person.objects.get(id=person_id).select_related('pets') # to cache the pets list within the person object avoiding future additional queries
treats = Treat.objects.filter(id__in=person.iter_importent_treats)
class Person(models.Model):
""" The 'a' from my above example """
@property
def iter_important_treats(self):
return iter(self.pets.values_list('treat_id', flat=True)) # caching will not affect the query behviour
person = Person.objects.get(id=person_id)
treats = Treat.objects.filter(id__in=person.iter_importent_treats)
注意:
treat_id
代替treat__id
来避免其他联接查询,因为django已经将treat_id
保存在Pet对象级别,但是如果您使用treat__id
那么就强迫加入查询。答案 1 :(得分:2)
以下内容应该符合您的要求:
def find_important_treats(self):
return Treat.objects.filter(id__in=person.pets.values_list('treat_id'))
它获得宠物拥有的ids
的所有Treat
,然后返回它们。