diff --git a/readthedocs/core/permissions.py b/readthedocs/core/permissions.py index 1c397eae11c..a3bfa04235c 100644 --- a/readthedocs/core/permissions.py +++ b/readthedocs/core/permissions.py @@ -9,6 +9,8 @@ class AdminPermissionBase: @classmethod def is_admin(cls, user, project): + # This explicitly uses "user in project.users.all" so that + # users on projects can be cached using prefetch_related or prefetch_related_objects return user in project.users.all() or user.is_superuser @classmethod diff --git a/readthedocs/projects/views/public.py b/readthedocs/projects/views/public.py index 2976cecb693..cc945b19676 100644 --- a/readthedocs/projects/views/public.py +++ b/readthedocs/projects/views/public.py @@ -13,6 +13,7 @@ from django.contrib.auth.models import User from django.core.cache import cache from django.core.files.storage import get_storage_class +from django.db.models import prefetch_related_objects from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse @@ -271,6 +272,9 @@ def project_versions(request, project_slug): if wiped and wiped_version.count(): messages.success(request, 'Version wiped: ' + wiped) + # Optimize project permission checks + prefetch_related_objects([project], 'users') + return render( request, 'projects/project_version_list.html',