具有三层深度嵌套模型的查询集过滤器(多个一对多关系)
Posted
技术标签:
【中文标题】具有三层深度嵌套模型的查询集过滤器(多个一对多关系)【英文标题】:Queryset filter with three-deep nested models (multiple one-to-many relationships) 【发布时间】:2017-02-03 07:33:45 【问题描述】:我试图弄清楚如何使用我的模型设置过滤 Django 中的一些查询:
class Team(models.Model):
name = models.CharField()
class TeamPosition(models.Model):
description = models.CharField()
team = models.ForeignKey(Team)
class Player(models.Model):
teamposition = models.ForeignKey(TeamPosition)
team = models.ForeignKey(Team)
joined_date = models.DateField()
left_date = models.DateField(blank=True, null=True)
person = models.ForeignKey(Person)
class Person(models.Model):
name = models.CharField()
我想找到回答这些问题的查询集(为了清楚起见,移到下面):
如果我从 TeamPosition 对象开始,则更容易弄清楚(但不会给我 Teams 的查询集)。
样本数据集:
对象集 1:
Team(name="Apples")
TeamPosition(team="Apples", description="Forward")
Player(team="Apples", teamposition="Forward", joined_date="2014-01-01", left_date=null, person="Bob")
TeamPosition(team="Apples", description="Defense")
Player(team="Apples", teamposition="Defense", joined_date="2014-01-01", left_date=2015-01-01, person="John")
Player(team="Apples", teamposition="Defense", joined_date="2015-01-01", left_date=2017-01-01, person="Paul")
TeamPosition(team="Apples", description="Goalie")
Player(team="Apples", teamposition="Goalie", joined_date="2014-01-01", left_date=2015-01-01, person="Jane")
对象集 2:
Team(name="Pears")
TeamPosition(team="Pears", description="Forward")
Player(team="Pears", teamposition="Forward", joined_date="2014-01-01", left_date=null, person="Carol")
TeamPosition(team="Pears", description="Defense")
Player(team="Pears", teamposition="Defense", joined_date="2015-01-01", left_date=2017-01-01, person="Bill")
TeamPosition(team="Pears", description="Goalie")
Player(team="Pears", teamposition="Goalie", joined_date="2014-01-01", left_date=null, person="Susan")
对象集 3:
Team(name="Oranges")
TeamPosition(team="Oranges", description="Forward")
TeamPosition(team="Oranges", description="Forward")
TeamPosition(team="Oranges", description="Goalie")
对象集 4:
Team(name="Bananas")
TeamPosition(team="Bananas", description="Forward")
Player(team="Bananas", teamposition="Forward", joined_date="2014-01-01", left_date=null, person="Joe")
TeamPosition(team="Bananas", description="Defense")
Player(team="Bananas", teamposition="Defense", joined_date="2015-01-01", left_date=2017-01-01, person="Angela")
TeamPosition(team="Bananas", description="Goalie")
Player(team="Bananas", teamposition="Goalie", joined_date="2014-01-01", left_date="2016-09-30", person="Kelly")
因此,基于这些对象,我希望得到以下结果:
哪些团队有可用的团队职位? (可用的意思是没有当前玩家的 TeamPosition)
Queryset should return Object 1 (Apples) and Object 3 (Oranges)
哪些球队的所有 TeamPosition 都已满员? (与上述相反)(当前表示未来没有 left_date 或 left_date 的玩家)
Queryset should return Object 2 (Pears) and Object 4 (Bananas)
哪些团队在 30 天内会有空的 TeamPosition?
Queryset should return Object 4 (Bananas)
希望这样可以更清楚。
注意:以前有一个汽车示例(因此是第一个响应),但似乎不清楚所以创建了一个更好的示例
【问题讨论】:
【参考方案1】:回答前的一个问题:carmodel = models.ForeignKey(Model)
行好吗?还是应该改成ForeignKey(CarModel)
?
试试这个查询(这应该会为您提供 CarModel 的 ModelYear 的 last_availability
日期在未来的所有 CarCompany 对象:
from datetime import datetime
CarCompany.objects.filter(carmodel__modelyear__last_availability__gte=datetime.now())
为了检查last_availability
是在未来还是空白/空,我会使用Q objects:
from django.db.models import Q
CarCompany.objects.filter(Q(carmodel__modelyear__last_availability__gte=datetime.now()) |
Q(carmodel__modelyear__last_availability__isnull=True))
对于您的第二个示例,我想不出但在同一个查询中(它回答了您的问题 Which Teams have open TeamPositions?
和 Which Teams will have an empty TeamPosition in 30 days
)
但我不确定Which Teams have no TeamPositions without current Players?
是什么意思,如果你能解释一下...
Team.objects.filter(Q(teamposition__player__left_date__gte=datetime.now()) |
Q(teamposition__player__left_date__isnull=True) |
【讨论】:
你说得对,应该是 CarModel。我会试试这个..! 进行了快速测试,删除了exact=''(我认为空白时日期总是为空,django 提醒了我)并添加了 distinct()。然而,我最终得到了我所有的测试对象(应该是大约一半)。我正在编辑我的问题以添加一组不同的示例类,这可能会更清楚。 我不明白为什么该查询不起作用。无论如何,我更新了我的答案。您能否澄清第二个示例中的Which Teams have no TeamPositions without current Players?
是什么意思?
即如果一个团队有 2 个 TeamPlayers,其中一个有一个 Player 对象,其 join_date 为昨天且没有 left_date,但另一个 TeamPlayer 对象要么没有与之关联的 Player,要么有一个 left_date 为去年的 Player。
查询有效...它只返回我所有测试数据的查询集。从理论上讲,它应该只返回 CarCompany 对象,这些对象的 CarModels 和 ModelYears 未来的 last_availability 或 last_availability 为 null。我有一个测试数据,其中有一个带有 CarModel 的 CarCompany 并且没有包含 ModelYear 对象,但是当我创建一个 ModelYear 对象时,该对象在从集合中删除之前很久就过期了。我认为当有多个 CarModel 时它会跳闸。以上是关于具有三层深度嵌套模型的查询集过滤器(多个一对多关系)的主要内容,如果未能解决你的问题,请参考以下文章