【问题标题】:Optimize django query with Exists, Subquery and OuterRef使用 Exists、Subquery 和 OuterRef 优化 django 查询
【发布时间】:2020-06-06 14:16:56
【问题描述】:

我需要帮助优化这个 django 查询。代码及用例如下:

我的代码:

  user_enrolments = UserEnrolment.objects.filter(
            enrolment__enrollable__id__in=course_ids_taught_by_teacher,
            course_progresses__module_progresses__module=instance).only("id").annotate(
            submitted_attempt=Exists(
                AssignmentModuleProgress.objects
                .annotate(user=OuterRef('id'))
                .filter(
                    module_progress=Subquery(
                    ModuleProgress.objects.get(module=instance, user=OuterRef('user'))),
                    is_submitted=True)
            ))
        return user_enrolments.filter(submitted_attempt=True).count()

course_progresses -> 多对多到 UserEnrolment, module_progress -> 多对多到 CourseProgress 和 instance 是序列化程序迭代中的当前 AssignmentModule。

我想在序列化器中获取提交的用户数,所以我使用序列化器方法字段。

要获取提交的用户数,我想检查 AssignmentModuleProgress 表中是否存在 module_progress = ModuleProgress.objects.get(module=instance, user=OuterRef('user')) 的条目 User 是 UserEnrolments 表中的一个字段,用户应该在 user_enrolments 注释迭代中引用当前用户。我在过滤 is_submitted 的 True 条件后返回计数。

截至目前,我收到以下错误:

ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.

【问题讨论】:

    标签: django django-models django-rest-framework django-queryset


    【解决方案1】:

    这可能是不使用子查询的解决方案:

      user_enrolments = UserEnrolment.objects.filter(
                enrolment__enrollable__id__in=course_ids_taught_by_teacher,
                course_progresses__module_progresses__module=instance).only("id").annotate(
                submitted_attempt=Exists(
                    AssignmentModuleProgress.objects
                    .annotate(user=OuterRef('pk'))
                    .filter(
                        Q(module_progress__module=instance) &
                        Q(module_progress__user=OuterRef('user')),
                        is_submitted=True)
                ))
            return user_enrolments.filter(submitted_attempt=True).count()
    

    【讨论】:

      猜你喜欢
      • 2018-04-22
      • 1970-01-01
      • 1970-01-01
      • 2018-04-16
      • 2017-05-25
      • 2022-01-08
      • 2018-11-08
      • 2021-09-17
      • 2016-02-23
      相关资源
      最近更新 更多