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
|
@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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 -%}
|
||||||
|
|
Loading…
Add table
Reference in a new issue