【问题标题】:Django reverse lookup chaining querysetDjango反向查找链接查询集
【发布时间】:2014-10-03 20:43:43
【问题描述】:

我有几个模型需要在其中进行反向查找,然后以某种方式将查询集链接在一起。

我有 3 个模型,(1) 设计师创建 (2) 个项目,并且项目包含 (3) 个上传的图像。

模型

class Designer(models.Model):
    ... 

class Project(models.Model):
    designer = models.ForeignKey('Designer')

class UploadedImage(models.Model):
    project = models.ForeignKey('Project')

所以设计师打开他的页面并想要查看他的所有项目以及与他的项目相关的一些图像,我可以这样做,

d = Designer.objects.get(id=2)
projects = d.project_set.all()

但是对于图像,我必须多次执行此操作,每次都访问数据库。

images = []
for p in projects:
    images.append(p.uploadedimage_set.all())

现在我们有另一个问题,我如何连接imagesprojects??我可以通过建立这样的字典来做一些愚蠢的事情,

images = []
for p in projects:
    images.append( { p.id : p.uploadedimage_set.all() } )

然后当我遍历projects 时,我可以使用id 来确定哪些图像与哪个项目相关联。

难道没有更优雅的东西可以让我这样做吗,

  1. 只需访问数据库一次
  2. 允许我做一些看起来像d.projects[0].images[0]的事情???而不是建立某种愚蠢的自定义字典??? Django 是否有某种查询集构建工具之类的?

谢谢!!

【问题讨论】:

  • 我无法访问控制台进行检查,但 iirc UploadedImage(project__designer=designer) 应该可以工作。同样UploadedImage(project__designer__in=listOfDesigners) 可以让你一次查询多个。
  • @sapi 我试过了,想出了这个似乎可以满足我的要求:images = UploadedImage.objects.filter(project__designer=d).prefetch_related(),我添加了最后一个预取部分,因为据说它缓存了查询。我仍然需要将项目放在一起,因为我不能完全折叠images 来获取项目(我可以,但以这种方式倒退似乎很愚蠢)。所以 net net 我两次访问 DB 以获得我想要的,这比我之前的要好得多。谢谢老兄。
  • @sapi 实际上,只是想到了一些事情,我可以在images 上写一些查询,然后将其缓存在本地以从中获取所有独特的项目吗?这样,它只有 1 个 DB 命中。
  • 您可以使用distinct(请参阅stackoverflow.com/questions/3852104/…),但在这一点上,我强烈怀疑您过早地进行了优化。您应该首先编写清晰的代码,并且只在极不可能的情况下优化数据库调用的数量,这被证明是一个瓶颈

标签: django reverse django-queryset


【解决方案1】:

如果您只关注与特定设计师关联的图片,您可以通过一个查询来获取它们:

designer = Designer.objects.get(id=id)
images = UploadedImage.objects.filter(product__designer=designer)

如果您想将它们与项目相关联,有几种方法可以做到这一点。

如果不同项目不多,又担心查询数据库过多,可以使用之前的images列表,在python中进行过滤:

images = list(images) # Crystallise the query
projectImages = [[img for img in images if img.project == p]
                 for p in designer.project_set.all()]

但是,更好的方法可能是让数据库处理过滤;对于非平凡大小的集合,它可能会更快。

这样就可以直接查询图片了,即:

designer = Designer.objects.get(id=id)
projects = designer.project_set.all() # Project.objects.filter(designer=designer)
projectImages = [UploadedImage.objects.filter(project=p) for p in projects]

第二种方法的最大优点是projectImages 中的元素仍然是查询集,因此仍然可以进一步过滤或注释。

【讨论】:

  • 获得了正确答案的功劳,但主要是因为 sapi 在问题的 cmets 中的回答。对我来说,cmets 解决了我的问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-01
  • 2014-02-16
  • 2018-03-24
  • 2013-02-01
  • 2015-02-09
相关资源
最近更新 更多