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

@ -3,34 +3,39 @@ from . import registry
@registry.function
def submission_layout(
submission, profile_id, user, editable_problem_ids, completed_problem_ids
submission,
profile_id,
user,
editable_problem_ids,
completed_problem_ids,
tester_problem_ids,
):
problem_id = submission.problem_id
can_view = False
if problem_id in editable_problem_ids:
can_view = True
return True
if problem_id in tester_problem_ids:
return True
if profile_id == submission.user_id:
can_view = True
return True
if user.has_perm("judge.change_submission"):
can_view = True
return True
if user.has_perm("judge.view_all_submission"):
can_view = True
return True
if submission.problem.is_public and user.has_perm("judge.view_public_submission"):
can_view = True
return True
if submission.problem_id in completed_problem_ids:
can_view |= (
submission.problem.is_public or profile_id in submission.problem.tester_ids
)
if not can_view and hasattr(submission, "contest"):
if hasattr(submission, "contest"):
contest = submission.contest.participation.contest
if contest.is_editable_by(user):
can_view = True
return True
return can_view
if submission.problem_id in completed_problem_ids and submission.problem.is_public:
return True
return False

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

View file

@ -191,6 +191,9 @@ class DiggPaginator(ExPaginator):
# validate padding value
max_padding = int(math.ceil(self.body / 2.0) - 1)
self.padding = kwargs.pop("padding", min(4, max_padding))
count_override = kwargs.pop("count", None)
if count_override is not None:
self.__dict__["count"] = count_override
if self.padding > max_padding:
raise ValueError("padding too large for body (max %d)" % max_padding)
super(DiggPaginator, self).__init__(*args, **kwargs)

View file

@ -19,14 +19,17 @@ __all__ = [
"contest_completed_ids",
"get_result_data",
"user_completed_ids",
"user_authored_ids",
"user_editable_ids",
"user_tester_ids",
]
def user_authored_ids(profile):
result = set(Problem.objects.filter(authors=profile).values_list("id", flat=True))
return result
def user_tester_ids(profile):
return set(
Problem.testers.through.objects.filter(profile=profile).values_list(
"problem_id", flat=True
)
)
def user_editable_ids(profile):

View file

@ -482,13 +482,10 @@ class ProblemList(QueryStringSortMixin, TitleMixin, SolvedProblemMixin, ListView
padding=2,
orphans=orphans,
allow_empty_first_page=allow_empty_first_page,
count=queryset.values("pk").count() if not self.in_contest else None,
**kwargs
)
if not self.in_contest:
# Get the number of pages and then add in this magic.
# noinspection PyStatementEffect
paginator.num_pages
queryset = queryset.add_i18n_name(self.request.LANGUAGE_CODE)
sort_key = self.order.lstrip("-")
if sort_key in self.sql_sort:
@ -670,8 +667,12 @@ class ProblemList(QueryStringSortMixin, TitleMixin, SolvedProblemMixin, ListView
if self.request.profile:
context["organizations"] = self.request.profile.organizations.all()
all_authors_ids = set(Problem.objects.values_list("authors", flat=True))
context["all_authors"] = Profile.objects.filter(id__in=all_authors_ids)
all_authors_ids = Problem.objects.values_list("authors", flat=True)
context["all_authors"] = (
Profile.objects.filter(id__in=all_authors_ids)
.select_related("user")
.values("id", "user__username")
)
context["category"] = self.category
context["categories"] = ProblemGroup.objects.all()
if self.show_types:

View file

@ -41,9 +41,7 @@ from judge.models import ProblemTranslation
from judge.models import Profile
from judge.models import Submission
from judge.utils.problems import get_result_data
from judge.utils.problems import user_authored_ids
from judge.utils.problems import user_completed_ids
from judge.utils.problems import user_editable_ids
from judge.utils.problems import user_completed_ids, user_editable_ids, user_tester_ids
from judge.utils.problem_data import get_problem_case
from judge.utils.raw_sql import join_sql_subquery, use_straight_join
from judge.utils.views import DiggPaginatorMixin
@ -476,12 +474,12 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
context["completed_problem_ids"] = (
user_completed_ids(self.request.profile) if authenticated else []
)
context["authored_problem_ids"] = (
user_authored_ids(self.request.profile) if authenticated else []
)
context["editable_problem_ids"] = (
user_editable_ids(self.request.profile) if authenticated else []
)
context["tester_problem_ids"] = (
user_tester_ids(self.request.profile) if authenticated else []
)
context["all_languages"] = Language.objects.all().values_list("key", "name")
context["selected_languages"] = self.selected_languages
@ -769,15 +767,15 @@ def single_submission(request, submission_id, show_problem=True):
"submission/row.html",
{
"submission": submission,
"authored_problem_ids": user_authored_ids(request.profile)
if authenticated
else [],
"completed_problem_ids": user_completed_ids(request.profile)
if authenticated
else [],
"editable_problem_ids": user_editable_ids(request.profile)
if authenticated
else [],
"tester_problem_ids": user_tester_ids(request.profile)
if authenticated
else [],
"show_problem": show_problem,
"problem_name": show_problem
and submission.problem.translated_name(request.LANGUAGE_CODE),

View file

@ -369,7 +369,6 @@ ul.problem-list {
margin-left: 2.5%;
padding-bottom: 1em;
border-radius: 5px;
margin-bottom: 1em;
display: flex;
justify-content: space-between;
}

View file

@ -59,7 +59,7 @@
<select id="search-author" name="authors" multiple>
{% for author in all_authors %}
<option value="{{ author.id }}"{% if author.id in author_query %} selected{% endif %}>
{{ author.user.username }}
{{ author.user__username }}
</option>
{% endfor %}
</select>

View file

@ -1,4 +1,4 @@
{% set can_view = submission_layout(submission, profile_id, request.user, editable_problem_ids, completed_problem_ids) %}
{% set can_view = submission_layout(submission, profile_id, request.user, editable_problem_ids, completed_problem_ids, tester_problem_ids) %}
<div class="sub-result {{ submission._result_class if in_hidden_subtasks_contest else submission.result_class }}">
<div class="score">
{%- if submission.is_graded -%}