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 @registry.function
def submission_layout( 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 problem_id = submission.problem_id
can_view = False
if problem_id in editable_problem_ids: 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: if profile_id == submission.user_id:
can_view = True return True
if user.has_perm("judge.change_submission"): if user.has_perm("judge.change_submission"):
can_view = True return True
if user.has_perm("judge.view_all_submission"): 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"): 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: if hasattr(submission, "contest"):
can_view |= (
submission.problem.is_public or profile_id in submission.problem.tester_ids
)
if not can_view and hasattr(submission, "contest"):
contest = submission.contest.participation.contest contest = submission.contest.participation.contest
if contest.is_editable_by(user): 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.cache import cache
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
from django.db import models 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.db.models.functions import Coalesce
from django.urls import reverse from django.urls import reverse
from django.utils.functional import cached_property from django.utils.functional import cached_property
@ -369,7 +369,7 @@ class Problem(models.Model):
) )
@classmethod @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. # Do unauthenticated check here so we can skip authentication checks later on.
if not user.is_authenticated or not user: if not user.is_authenticated or not user:
return cls.get_public_problems() 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` # - not is_organization_private or in organization or `judge.see_organization_problem`
# - author or curator or tester # - author or curator or tester
queryset = cls.objects.defer("description") queryset = cls.objects.defer("description")
profile = profile or user.profile
if not ( if not (
user.has_perm("judge.see_private_problem") user.has_perm("judge.see_private_problem")
or user.has_perm("judge.edit_all_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. # Either not organization private or in the organization.
q &= Q(is_organization_private=False) | Q( q &= Q(is_organization_private=False) | Q(
is_organization_private=True, 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. # Authors, curators, and testers should always have access, so OR at the very end.
q |= Q(authors=user.profile) filter = Exists(
q |= Q(curators=user.profile) Problem.authors.through.objects.filter(
q |= Q(testers=user.profile) 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) queryset = queryset.filter(q)
return queryset return queryset

View file

@ -191,6 +191,9 @@ class DiggPaginator(ExPaginator):
# validate padding value # validate padding value
max_padding = int(math.ceil(self.body / 2.0) - 1) max_padding = int(math.ceil(self.body / 2.0) - 1)
self.padding = kwargs.pop("padding", min(4, max_padding)) 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: if self.padding > max_padding:
raise ValueError("padding too large for body (max %d)" % max_padding) raise ValueError("padding too large for body (max %d)" % max_padding)
super(DiggPaginator, self).__init__(*args, **kwargs) super(DiggPaginator, self).__init__(*args, **kwargs)

View file

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

View file

@ -482,13 +482,10 @@ class ProblemList(QueryStringSortMixin, TitleMixin, SolvedProblemMixin, ListView
padding=2, padding=2,
orphans=orphans, orphans=orphans,
allow_empty_first_page=allow_empty_first_page, allow_empty_first_page=allow_empty_first_page,
count=queryset.values("pk").count() if not self.in_contest else None,
**kwargs **kwargs
) )
if not self.in_contest: 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) queryset = queryset.add_i18n_name(self.request.LANGUAGE_CODE)
sort_key = self.order.lstrip("-") sort_key = self.order.lstrip("-")
if sort_key in self.sql_sort: if sort_key in self.sql_sort:
@ -670,8 +667,12 @@ class ProblemList(QueryStringSortMixin, TitleMixin, SolvedProblemMixin, ListView
if self.request.profile: if self.request.profile:
context["organizations"] = self.request.profile.organizations.all() context["organizations"] = self.request.profile.organizations.all()
all_authors_ids = set(Problem.objects.values_list("authors", flat=True)) all_authors_ids = Problem.objects.values_list("authors", flat=True)
context["all_authors"] = Profile.objects.filter(id__in=all_authors_ids) context["all_authors"] = (
Profile.objects.filter(id__in=all_authors_ids)
.select_related("user")
.values("id", "user__username")
)
context["category"] = self.category context["category"] = self.category
context["categories"] = ProblemGroup.objects.all() context["categories"] = ProblemGroup.objects.all()
if self.show_types: if self.show_types:

View file

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

View file

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

View file

@ -59,7 +59,7 @@
<select id="search-author" name="authors" multiple> <select id="search-author" name="authors" multiple>
{% for author in all_authors %} {% for author in all_authors %}
<option value="{{ author.id }}"{% if author.id in author_query %} selected{% endif %}> <option value="{{ author.id }}"{% if author.id in author_query %} selected{% endif %}>
{{ author.user.username }} {{ author.user__username }}
</option> </option>
{% endfor %} {% endfor %}
</select> </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="sub-result {{ submission._result_class if in_hidden_subtasks_contest else submission.result_class }}">
<div class="score"> <div class="score">
{%- if submission.is_graded -%} {%- if submission.is_graded -%}