子查询中的 Django 回合

Django round in subquery

您好,我正在使用以下代码获取带有子查询的 ListView 中每个项目的进度百分比

class projects(LoginRequiredMixin, ListView):
    model = Project
    template_name = 'project_list.html'
    ordering = ['project_title']
    paginate_by = 10
    queryset = Project.objects.annotate(
        todo_done=Count('todo', filter=Q(todo__state=True)) * 100 / Count('todo'),
        todo_left=Count('todo', filter=Q(todo__state=False)) * 100 / Count('todo'),
    )

在一个项目中,我有 12 个任务,8 个已完成,4 个正在进行中。系统returns完成66%,进行中33%,其总和是99%而不是100%

{{ project.todo_done }}
{{ project.todo_left }}

部分栏为空白,因为缺少 1%。我尝试如下使用 round 但这是不可能的

todo_done=round(Count('todo', filter=Q(todo__state=True)) * 100 / Count('todo')),
TypeError: type CombinedExpression doesn't define __round__ method

您不能使用 Python 的 round,因为它对数据库表达式一无所知。但是你可以使用 Round expression [Django-doc]:

from django.db.models import F
from django.db.models.functions import <b>Round</b>

queryset = Project.objects.annotate(
    todo_done=<b>Round(</b>Count('todo', filter=Q(todo__state=True)) * 100 / Count('todo')<b>)</b>,
    todo_left=100*Count('todo') - F('todo_done'),
)

如果Todostate只能是TrueFalse,那么100次减去todo_done可能更好Count('todo'),从此以后正常保证两者相加为100,当然除非有没有个相关的Todo

如果两个操作数是整数,有些数据库会使用整数除法,您可以通过将其转换为 FloatField:

来防止这种情况
from django.db.models import F, FloatField
from django.db.models.functions import <b>Cast</b>, Round

queryset = Project.objects.annotate(
    todo_done=<b>Round(</b>
        <b>Cast(</b>Count('todo', filter=Q(todo__state=True)), output_field=FloatField()<b>)</b>
        * 100 / Count('todo')
    <b>)</b>,
    todo_left=100*Count('todo') - F('todo_done'),
)