我想减少类似查询的数量。以下是我的模型:
class Skill(models.Model):
name = models.TextField()
class Employee(models.Model):
firstname = models.TextField()
skills = models.ManyToManyField(Skill, through='SkillStatus')
def skills_percentage(self):
completed = 0
total = 0
for skill in self.skills.all().prefetch_related("skillstatus_set__employee"):
for item in skill.skillstatus_set.all():
if item.employee.firstname == self.firstname:
total += 1
if item.status:
completed += 1
try:
percentage = round((completed / total * 100), 2)
except ZeroDivisionError:
percentage = 0.0
return f"{percentage} %"
class SkillStatus(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
skill = models.ForeignKey(Skill, on_delete=models.CASCADE)
status = models.BooleanField(default=False)
我的主要问题是关于skills_percentage方法,我在计算提到的值时做了太多的查询。我已经用prefetch_related稍微改善了一些情况,但是Django调试工具栏中仍然有额外的查询。这里还能做什么?
我试过使用select_related和prefetch_related的不同组合。我想过其他选项来计算skills_percentage,但它们也需要许多查询。
先谢了。
2条答案
按热度按时间luaexgnf1#
你可以这样尝试:
这里我计算了两次技能,第一次没有total条件,第二次使用了过滤条件,然后我用原始的queryset注解了completed/total值的除法,将其转换为
FloatField
。erhoui1w2#
可以使用Django的ORM提供的聚合函数,这有助于减少计算员工已完成技能和总技能计数所需的查询数量。
使用F()表达式和annotate()允许我们在单个查询中执行计算,而不需要在相关的Skill对象上进行单独的循环。