Some more optimizations

This commit is contained in:
cuom1999 2023-02-18 16:38:47 -06:00
parent a9dc97a46d
commit 3f6841932b
9 changed files with 65 additions and 44 deletions

View file

@ -6,7 +6,7 @@ from django.contrib.contenttypes.fields import GenericRelation
from django.core.cache import cache
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
from django.db import models
from django.db.models import CASCADE, F, FilteredRelation, Q, SET_NULL
from django.db.models import CASCADE, F, FilteredRelation, Q, SET_NULL, Exists, OuterRef
from django.db.models.functions import Coalesce
from django.urls import reverse
from django.utils.functional import cached_property
@ -369,7 +369,7 @@ class Problem(models.Model):
)
@classmethod
def get_visible_problems(cls, user):
def get_visible_problems(cls, user, profile=None):
# Do unauthenticated check here so we can skip authentication checks later on.
if not user.is_authenticated or not user:
return cls.get_public_problems()
@ -383,7 +383,7 @@ class Problem(models.Model):
# - not is_organization_private or in organization or `judge.see_organization_problem`
# - author or curator or tester
queryset = cls.objects.defer("description")
profile = profile or user.profile
if not (
user.has_perm("judge.see_private_problem")
or user.has_perm("judge.edit_all_problem")
@ -393,13 +393,25 @@ class Problem(models.Model):
# Either not organization private or in the organization.
q &= Q(is_organization_private=False) | Q(
is_organization_private=True,
organizations__in=user.profile.organizations.all(),
organizations__in=profile.organizations.all(),
)
# Authors, curators, and testers should always have access, so OR at the very end.
q |= Q(authors=user.profile)
q |= Q(curators=user.profile)
q |= Q(testers=user.profile)
filter = Exists(
Problem.authors.through.objects.filter(
problem=OuterRef("pk"), profile=profile
)
)
filter |= Exists(
Problem.curators.through.objects.filter(
problem=OuterRef("pk"), profile=profile
)
)
filter |= Exists(
Problem.testers.through.objects.filter(
problem=OuterRef("pk"), profile=profile
)
)
queryset = queryset.filter(q)
return queryset