繁体   English   中英

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}] 我需要返回拥有 5 年 xp 的 python 或 2 年的节点 xp 的开发人员?

我认为最简单的方法是确定所有技能的总和,然后检查其中至少一项是否满足约束条件,因此:

# 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',
        filter=Q(experience__skill_experience__skill__code=di['code'])
    ) 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等属性,用于包含该技能年数总和的列表中的每个技能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM