Django ORM 过滤器 SUM 循环中的不同相关对象
Django ORM filter SUM different related objects on a loop
我有以下型号:
class Developer(models.Model):
name = models.CharField(max_length=100)
class Skill(models.Model):
code = models.CharField(max_length=30)
class Experience(models.Model):
date_from = models.DateField(blank=True, null=True)
date_to = models.DateField(blank=True, null=True)
developer = models.ForeignKey(Developer, related_name='experience',
on_delete=models.CASCADE)
class SkillExperience(models.Model):
skill = models.ForeignKey(Skill, on_delete=models.CASCADE, related_name='skill_experience')
experience = models.ForeignKey(Experience, on_delete=models.CASCADE, related_name='skill_experience')
years_experience = models.IntegerField()
我知道对于单个查询,要让开发人员在 Python 方面至少有 5 年的经验,我可以这样做:
Developer.objects.filter(
experience__skill_experience__skill__code='Python'
).annotate(
total_years=Sum('experience__skill_experience__years_experience')
).filter(
total_years__gte=5
)
但是,如果我处于技能循环中并且需要检查 OR,那么假设循环这个数组:[{code: 'python', years_experience: 5 }, {code: 'node', years_experience: 2}] 我需要 return 有 5 年经验的 python 或 2 年经验的开发者?
我认为最简单的方法是确定所有技能的总和,然后检查其中至少一项是否满足约束条件,因此:
# since Django-2.0
from django.db.models import Q, Sum
# sample data
data = [
{code: 'python', years_experience: 5},
{code: 'node', years_experience: 2}
]
annotates = {
f'total_years_{i}': Sum(
'experience__skill_experience__years_experience',
<b>filter=Q(experience__skill_experience__skill__code=di['code'])</b>
) for i, di in enumerate(data)
}
qs = Q(
*[(f'total_years_{i}__gte', di['years_experience']) for i, di in enumerate(data)],
_connector=Q.OR
)
developers = Developer.objects.annotate(
**annotates
).filter(
qs
)
作为奖励,developers
中的 Developer
个对象将具有 .total_years_0
、.total_years_1
等列表中包含总和的每个技能的属性该技能的年份。
我有以下型号:
class Developer(models.Model):
name = models.CharField(max_length=100)
class Skill(models.Model):
code = models.CharField(max_length=30)
class Experience(models.Model):
date_from = models.DateField(blank=True, null=True)
date_to = models.DateField(blank=True, null=True)
developer = models.ForeignKey(Developer, related_name='experience',
on_delete=models.CASCADE)
class SkillExperience(models.Model):
skill = models.ForeignKey(Skill, on_delete=models.CASCADE, related_name='skill_experience')
experience = models.ForeignKey(Experience, on_delete=models.CASCADE, related_name='skill_experience')
years_experience = models.IntegerField()
我知道对于单个查询,要让开发人员在 Python 方面至少有 5 年的经验,我可以这样做:
Developer.objects.filter(
experience__skill_experience__skill__code='Python'
).annotate(
total_years=Sum('experience__skill_experience__years_experience')
).filter(
total_years__gte=5
)
但是,如果我处于技能循环中并且需要检查 OR,那么假设循环这个数组:[{code: 'python', years_experience: 5 }, {code: 'node', years_experience: 2}] 我需要 return 有 5 年经验的 python 或 2 年经验的开发者?
我认为最简单的方法是确定所有技能的总和,然后检查其中至少一项是否满足约束条件,因此:
# since Django-2.0
from django.db.models import Q, Sum
# sample data
data = [
{code: 'python', years_experience: 5},
{code: 'node', years_experience: 2}
]
annotates = {
f'total_years_{i}': Sum(
'experience__skill_experience__years_experience',
<b>filter=Q(experience__skill_experience__skill__code=di['code'])</b>
) for i, di in enumerate(data)
}
qs = Q(
*[(f'total_years_{i}__gte', di['years_experience']) for i, di in enumerate(data)],
_connector=Q.OR
)
developers = Developer.objects.annotate(
**annotates
).filter(
qs
)
作为奖励,developers
中的 Developer
个对象将具有 .total_years_0
、.total_years_1
等列表中包含总和的每个技能的属性该技能的年份。