From 96c789014f682eb9bd8eef98d1fe59ca03516e1b Mon Sep 17 00:00:00 2001 From: mirabilos <thorsten.glaser@teckids.org> Date: Tue, 3 Sep 2019 23:32:26 +0200 Subject: [PATCH] =?UTF-8?q?Use=20an=20SQL=20=E2=80=9CWHERE=20NOT=20EXISTS?= =?UTF-8?q?=E2=80=9D=20subclause.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is correct performance-wise (avoids the need for the database to build the entire result set before filtering; Django users reported a speed-up of factor 5‥2000 over naïve solutions) and (accepted by Nik) even more legible. --- biscuit/apps/alsijil/views.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/biscuit/apps/alsijil/views.py b/biscuit/apps/alsijil/views.py index 69e10cdcd..57d1ab82b 100644 --- a/biscuit/apps/alsijil/views.py +++ b/biscuit/apps/alsijil/views.py @@ -2,7 +2,7 @@ from collections import OrderedDict from typing import Optional from django.contrib.auth.decorators import login_required -from django.db.models import Q +from django.db.models import Exists, OuterRef, Q from django.http import HttpRequest, HttpResponse from django.shortcuts import render from django.views.decorators.cache import cache_page @@ -41,13 +41,17 @@ def lesson(request: HttpRequest, week: Optional[int] = None, period_id: Optional request.POST or None, instance=lesson_documentation, prefix='leson_documentation') # Create all missing personal notes about members of all groups in lesson - missing_persons = Person.objects.filter( + missing_persons = Person.objects.annotate( + no_personal_notes=~Exists(PersonalNote.objects.filter( + week=wanted_week, + lesson_period=lesson_period, + person__pk=OuterRef('pk') + )) + ).filter( member_of__in=Group.objects.filter(pk__in=lesson_period.lesson.groups.all()), - is_active=True - ).exclude( - personal_notes__week=wanted_week, - personal_notes__lesson_period=lesson_period - ).all() + is_active=True, + no_personal_notes=True + ) PersonalNote.objects.bulk_create([ PersonalNote(person=person, lesson_period=lesson_period, week=wanted_wek) for person in missing_persons -- GitLab