【问题标题】:How Do I Select all Objects via a Relationship Model如何通过关系模型选择所有对象
【发布时间】:2010-11-26 16:30:31
【问题描述】:

给定模型:

class Profile(models.Model):
    user = models.ForeignKey(User, unique=True)

class Thingie(models.Model):
    children = models.ManyToManyField('self', blank=True, symmetrical=False) 

class Relation(models.Model):
    profile = models.ForeignKey(Profile)
    thingie = models.ForeignKey(Thingie)

如何返回包含与给定 Thingie 相关的所有 Profile 实例的 QuerySet?也就是说,每个配置文件都有一个从关系指向它和给定事物的外键。

我知道所有关于 select_related() 的知识,以及如何通过迭代来使用它来做到这一点,但我发现迭代很烦人(badoop bah!)。此外,已经查看了 values_list(),但它并没有做正确的事情。

请帮忙!谢谢!

【问题讨论】:

  • 嗯? Profile和Relation是什么关系? Relation和Thingie是什么关系?什么是 GrooveUser 和媒体?请尝试将您的问题提炼成最简单、有意义的形式。
  • 我的错,我不小心留下了一些真实的代码,而不是简化的 sn-p/example 代码。现已修复,谢谢!

标签: python django django-queryset


【解决方案1】:

你肯定需要它作为一个查询集吗?如果您只需要它是一个可迭代的,那么一个简单的表达式就是:

profiles = [r.profile for r in thingie.relation_set.all()]

我不确定列表理解是否算作令人讨厌的迭代,但对我来说,这是一种非常直观的 Python 方法。当然,如果你需要它成为一个查询集,你会用两个查询做一些更麻烦的事情,例如:

relation_values = thingie.relation_set.all().values_list('pk', flat=True)
profiles = Profile.objects.filter(relation__in=relation_values)

有关更多信息,请参阅“in”文档。如果您不需要查询集,我更喜欢第一种方法。哦,如果你只想要不同的配置文件,你可以在第一种方法中使用set(profiles),或者在第二种方法中使用distinct() queryset 方法。

【讨论】:

  • 列表理解肯定效果很好,但 OP 抱怨迭代(这基本上是列表理解所做的)......
【解决方案2】:

您是否阅读了Making queries 上的 Django 文档?它有一个简单的例子来实现你想要的,更具体地说是Lookups that span relationships。确保您将后面链接中的代码 sn-ps 引用到页面开头的模型代码。

【讨论】:

  • 是的,我已经阅读了很多次端到端的文档。但是,我似乎只能通过跨越关系来获得比较信息(即:找到我所有的东西,其中thingie.profile.user = X),而不是实际实例本身(即:找到我所有的关系.profiles whererelation.thingie = y)。
【解决方案3】:

如果不定义 Profile 和 Thingie 之间的直接关系,则不能。

最好的方法是向 Thingie 添加一个指向 Profile 的 ManyToMany,并在 ManyToMany 上使用 through 参数 (django docs) 来指定您的关系模型/表。

这样您就可以在 Thingie 上执行直接过滤操作以获取您的个人资料并仍然存储您的中间关系数据。

【讨论】:

  • 我可能最终会使用它,因为它更符合 Django 最佳实践,但我觉得上述答案的第二部分更准确地解决了这个问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多