Python 如何加入Django?
我有以下型号:Python 如何加入Django?,python,django,django-queryset,Python,Django,Django Queryset,我有以下型号: class Part(models.Model): user = models.ForeignKey(User) part_number = models.CharField() class Inventory(models.Model): user = models.ForeignKey(User) part = models.ForeignKey(Part) stock = models.IntegerField() stor
class Part(models.Model):
user = models.ForeignKey(User)
part_number = models.CharField()
class Inventory(models.Model):
user = models.ForeignKey(User)
part = models.ForeignKey(Part)
stock = models.IntegerField()
storage_location = ...
class Project(models.Model):
user = models.ForeignKey(User)
name = models.CharField()
class ProjectItem(models.Model):
project = models.ForeignKey(Project)
part = models.ForeignKey(Part)
quantity = models.IntegerField()
给定零件可以有多个库存
对象,每个存储位置一个。给定一个项目
,我想获得所有项目
的列表,以及每个项目
部分对应的库存
对象。对于Django查询,这可能吗
我可以
for pi in ProjectItem.objects.filter(project=project):
for inv in Inventory.objects.filter(user=user, part=pi.part)
...
但我不想对每个项目项进行查询。我想做:
project_items = ProjectItem.objects.filter(project=project,
part__inventory__user=user)
但我不知道如何提取查询中匹配的库存对象
有什么想法吗
编辑:让我用一个例子来说明。修复一个项目
a和一个用户
a。以下是一些表格(省略了Project
和User
)
项目项
:
Part Quantity
-----------------------
X 2
Y 1
库存
:
Part Stock Location
---------------------
X 91 S
X 13 T
Y 14 S
Y 101 U
我想要的(表格形式)是:
也就是说,我只想加入ProjectItem
和Inventory
以及part
和user
编辑2:一种可能是执行两个查询(对象、相关对象)并在Python中执行连接,如下所述:
与在数据库中进行连接相比,我认为这不是有效的,但它可能比n+1查询要好
prefetch_related(*lookups)
返回一个查询集,该查询集将在单个批处理中自动检索每个指定查找的相关对象
您需要使用预回迁相关工具,这是与选择相关工具的扩展。它们都是有用的工具,可以帮助您在对相关模型进行筛选时防止多个数据库命中 这是一个性能提升器,其结果是(有时要大得多) 查询,但这意味着以后不需要使用外键关系 数据库查询。 () prefetch_related与select_related类似,但使用pythonic(非常可靠地优化)代码来连接不同的查询。在您的情况下,我认为您必须使用预取_相关,因为您正在经历一个反向关系(从零件到库存)。在代码中,这将如下所示:
project_items = ProjectItem.objects.filter(project=project, part__inventory__user=user).prefetch_related('part__inventory_set')
for pi in project items:
for pi.part.inventory_set.all():
...
看起来好像每次都在访问数据库,但当使用prefetch_related时,django知道在调用pi.part.inventory_set.all()
时不要再次访问数据库,而是从缓存中获取它
重要提示-这不是一个神奇的函数,它只适用于all()
。使用pi.part.inventory\u set.filter(…)
将导致额外的查询,因此请谨慎使用 您可以使用它来帮助您检索任何相关数据。比如
ProjectItem.objects.all().extra(select={'inventory__stock':'stock','inventory__location':'location'}).values('part', 'quantity', 'stock','location')
希望这对你有帮助。
谢谢:)1。你所拥有的是一个。2.你能把你的问题扩大一点,并加上你想要的最终结果吗?我很难理解你所遇到的问题…看看你的显示方式,似乎没有办法摆脱双重循环。先别管查询了,在连接的表中,您必须在某个地方有一些重复,您将循环所有项目项,然后循环所有相关的库存项。。。如果同一项目中有许多库存项目,如何显示?也许你真正想做的是过滤零件对象(哪种连接所有东西)?我试着用一个例子来代表我在应用程序中的几个不同关系。我猜有两种情况:(1)每个(用户、部件)对的库存是唯一的。在这种情况下,没有重复。我还是不知道该怎么办。(2) 我想要复制,但需要迭代。在本例中,从概念上讲,我希望使用我上面写的for循环,但出于性能原因,我不希望内部循环命中数据库。因此,需要使用prefetche\u related或select\u related,以防止命中数据库以进一步调用相关模型。你也可能对Q对象的复杂查找感兴趣:prefetch_需要一个字符串,它不能像你的答案所建议的那样进行复杂的过滤(我也测试了你的解决方案,但它不起作用),它应该是
project\u items=ProjectItem.objects.filter(project=project).prefetch\u related('part\u inventory\u set\u user')
@yuvi感谢您指出我的字符串错误。很高兴我们同意与预回迁相关的做法。
ProjectItem.objects.all().extra(select={'inventory__stock':'stock','inventory__location':'location'}).values('part', 'quantity', 'stock','location')