From c87d3741f364e4907508de5b927bc8b7299f03af Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Wed, 23 Jan 2019 18:40:39 +0000 Subject: [PATCH] Added 2 utility functions to help create group features query filters, and applied them in 3 places in order to move group feature role list code back into DB queries. - Legacy-Id: 15911 --- ietf/doc/templatetags/managed_groups.py | 15 ++++++++------- ietf/doc/views_doc.py | 8 ++++---- ietf/group/utils.py | 25 +++++++++++++++++++++++++ ietf/submit/views.py | 7 ++++--- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/ietf/doc/templatetags/managed_groups.py b/ietf/doc/templatetags/managed_groups.py index 19a38528d..0db6b1367 100644 --- a/ietf/doc/templatetags/managed_groups.py +++ b/ietf/doc/templatetags/managed_groups.py @@ -1,6 +1,9 @@ from django import template -from ietf.group.models import Group, Role +import debug # pyflakes:ignore + +from ietf.group.models import Group +from ietf.group.utils import group_features_group_filter register = template.Library() @@ -9,12 +12,10 @@ def managed_groups(user): if not (user and hasattr(user, "is_authenticated") and user.is_authenticated): return [] - groups = [ g for g in Group.objects.filter( - role__person__user=user, - type__features__has_session_materials=True, - state__slug__in=('active', 'bof')).select_related("type") - if Role.objects.filter(group=g, person__user=user, name__slug__in=g.type.features.matman_roles) ] - + groups = Group.objects.filter( role__person=user.person, + type__features__has_session_materials=True, + state__slug__in=('active', 'bof')) + groups = group_features_group_filter(groups, user.person, 'matman_roles') return groups @register.filter diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index 8ed85e528..d45517075 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -1,5 +1,5 @@ # Copyright The IETF Trust 2016-2018, All Rights Reserved - +# -*- coding: utf-8 -*- # Parts Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -54,7 +54,7 @@ from ietf.doc.utils import ( add_links_in_new_revision_events, augment_events_wi add_events_message_info, get_unicode_document_content, build_doc_meta_block) from ietf.community.utils import augment_docs_with_tracking_info from ietf.group.models import Role -from ietf.group.utils import can_manage_group_type, can_manage_materials +from ietf.group.utils import can_manage_group_type, can_manage_materials, group_features_role_filter from ietf.ietfauth.utils import ( has_role, is_authorized_in_doc_stream, user_is_person, role_required, is_individual_draft_author) from ietf.name.models import StreamName, BallotPositionName @@ -164,8 +164,8 @@ def document_main(request, name, rev=None): # For some reason, AnonymousUser has __iter__, but is not iterable, # which causes problems in the filter() below. Work around this: if request.user.is_authenticated: - roles = [ r for r in Role.objects.filter(group__acronym__in=stream_slugs, person__user=request.user) - if r.name.slug in r.group.type.features.matman_roles ] + roles = Role.objects.filter(group__acronym__in=stream_slugs, person__user=request.user) + roles = group_features_role_filter(roles, request.user.person, 'matman_roles') else: roles = [] can_change_stream = bool(can_edit or roles) diff --git a/ietf/group/utils.py b/ietf/group/utils.py index f72c51ff8..b71ab5f38 100644 --- a/ietf/group/utils.py +++ b/ietf/group/utils.py @@ -1,5 +1,9 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved +# -*- coding: utf-8 -*- + import os +from django.db.models import Q from django.shortcuts import get_object_or_404 from django.utils.safestring import mark_safe from django.urls import reverse as urlreverse @@ -11,6 +15,7 @@ from ietf.community.utils import reset_name_contains_index_for_rule, can_manage_ from ietf.doc.models import Document, State from ietf.group.models import Group, RoleHistory, Role from ietf.ietfauth.utils import has_role +from ietf.name.models import GroupTypeName from ietf.person.models import Email from ietf.review.utils import can_manage_review_requests_for_team from ietf.utils import log @@ -246,3 +251,23 @@ def construct_group_menu_context(request, group, selected, group_type, others): d.update(others) return d + + +def group_features_group_filter(groups, person, feature): + """This returns a queryset of groups filtered such that the given person has + a role listed in the given feature for each group.""" + type_slugs = set(groups.values_list('type__slug', flat=True)) + group_types = GroupTypeName.objects.filter(slug__in=type_slugs) + if not group_types.exists(): + return groups.none() + q = reduce(lambda a,b:a|b, [ Q(role__person=person, role__name__slug__in=getattr(t.features, feature)) for t in group_types ]) + return groups.filter(q) + +def group_features_role_filter(roles, person, feature): + type_slugs = set(roles.values_list('group__type__slug', flat=True)) + group_types = GroupTypeName.objects.filter(slug__in=type_slugs) + if not group_types.exists(): + return roles.none() + q = reduce(lambda a,b:a|b, [ Q(person=person, name__slug__in=getattr(t.features, feature)) for t in group_types ]) + return roles.filter(q) + diff --git a/ietf/submit/views.py b/ietf/submit/views.py index 57e09f4da..3984f3f8c 100644 --- a/ietf/submit/views.py +++ b/ietf/submit/views.py @@ -1,4 +1,5 @@ # Copyright The IETF Trust 2007-2019, All Rights Reserved +# -*- coding: utf-8 -*- import re import base64 @@ -17,7 +18,8 @@ import debug # pyflakes:ignore from ietf.doc.models import Document, DocAlias, AddedMessageEvent from ietf.doc.utils import prettify_std_name -from ietf.group.models import Group, Role +from ietf.group.models import Group +from ietf.group.utils import group_features_group_filter from ietf.ietfauth.utils import has_role, role_required from ietf.mailtrigger.utils import gather_address_lists from ietf.message.models import Message, MessageAttachment @@ -513,8 +515,7 @@ def add_preapproval(request): groups = Group.objects.filter(type__features__acts_like_wg=True).exclude(state__in=["conclude","bof-conc"]).order_by("acronym").distinct() if not has_role(request.user, "Secretariat"): - groups = [ g for g in groups.filter(role__person__user=request.user) - if Role.objects.filter(group=g, person__user=request.user, name__slug__in=g.type.features.matman_roles).exists() ] + groups = group_features_group_filter(groups, request.user.person, 'matman_roles') if request.method == "POST": form = PreapprovalForm(request.POST)