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')