Some more optimizations
This commit is contained in:
parent
a9dc97a46d
commit
3f6841932b
9 changed files with 65 additions and 44 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 -%}
|
||||
|
|
Loading…
Reference in a new issue