Ste*_*ier 5 python django django-models django-queryset python-3.x
我有一个系统,其中存在多个与一个模型的关系(比如说a 1 - >很多b),并且许多模型与另一个模型具有一对一的关系(比如说1b - > 1 c).如此绘制:
/--- b1 --- c1
/
a ---- b2 --- c2
\
\--- b3 --- c3
Run Code Online (Sandbox Code Playgroud)
我决定创建一个方法,收集所有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
Run Code Online (Sandbox Code Playgroud)
我根据您的用例建议两个几乎相似的解决方案:
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)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
注意:
treat_id来treat__id避免额外的连接查询,因为 django 已经treat_id在 Pet 对象级别保存了,但是如果您使用treat__id,那么您会强制执行连接查询。