Source code for oioioi.rankings.views

from django.conf import settings
from django.contrib import messages
from django.http import Http404
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.views.decorators.http import require_POST

from oioioi.base.menu import menu_registry
from oioioi.base.permissions import enforce_condition, make_request_condition
from oioioi.base.utils.user_selection import get_user_hints_view
from oioioi.contests.models import Submission
from oioioi.contests.utils import (
    can_enter_contest,
    contest_exists,
    is_contest_basicadmin,
)
from oioioi.rankings.forms import FilterUsersInRankingForm
from oioioi.rankings.models import Ranking


@make_request_condition
[docs]def has_any_ranking_visible(request): ccontroller = request.contest.controller rcontroller = ccontroller.ranking_controller() return ccontroller.can_see_ranking(request) and bool( rcontroller.available_rankings(request) )
@enforce_condition(contest_exists & can_enter_contest & is_contest_basicadmin) @enforce_condition(has_any_ranking_visible)
[docs]def get_users_in_ranking_view(request): queryset = Submission.objects return get_user_hints_view(request, 'substr', queryset, 'user')
@menu_registry.register_decorator( _("Ranking"), lambda request: reverse( 'default_ranking', kwargs={'contest_id': request.contest.id} ), order=440, ) @enforce_condition(contest_exists & can_enter_contest) @enforce_condition(has_any_ranking_visible, template='rankings/no_rankings.html')
[docs]def ranking_view(request, key=None): rcontroller = request.contest.controller.ranking_controller() choices = rcontroller.available_rankings(request) if key is None: key = choices[0][0] if key not in next(zip(*choices)): raise Http404 context = dict() ranking = None if rcontroller.can_search_for_users(): form = FilterUsersInRankingForm(request, request.GET) context['form'] = form if form.is_valid(): user = form.cleaned_data.get('user') # Everybody can search for themselves. # Contest admins can search for anyone. if user and (is_contest_basicadmin(request) or user == request.user): found_pos = rcontroller.find_user_position(request, key, user) if found_pos: users_per_page = getattr(settings, 'PARTICIPANTS_ON_PAGE', 100) found_page = ((found_pos - 1) // users_per_page) + 1 get_dict = request.GET.copy() get_dict.pop('user') get_dict['page'] = str(found_page) return redirect( request.path + '?' + get_dict.urlencode() + '#' + str(user.id) ) else: msg = _("User is not in the ranking.") # Admin should receive error in form, # whereas user should see it as an error message, # because there is no form then. if is_contest_basicadmin(request): form._errors['user'] = form.error_class([msg]) else: messages.error(request, msg) if ranking is None: # Changing request.GET is necessary! # The pagination library not only truncates the list of objects, # but also generates the links to other pages. # It simply copies the current url and replaces 'page' # with another number. If there is a different GET parameter, # it is included (without any change) in the url to another page. # If a user requests a page, he can provide any number of useless # GET parameters, which will be shown in urls to other pages. # The ranking page could be cached and those urls could be # visible to other users, giving them links to the ranking # with strange arguments (e.g. arguments, which perform a search). # Below, only 'user' key is deleted, because that's the only argument # performing an action, and I'd like to change request.GET # as less as possible. # This solution does not prevent users from sending "messages" # between each other (using these GET parameters). request.GET = request.GET.copy() try: request.GET.pop('user') except KeyError: pass ranking = rcontroller.get_rendered_ranking(request, key) context['choices'] = choices context['ranking'] = ranking context['key'] = key return TemplateResponse(request, 'rankings/ranking_view.html', context)
@enforce_condition(contest_exists & is_contest_basicadmin)
[docs]def ranking_csv_view(request, key): rcontroller = request.contest.controller.ranking_controller() choices = rcontroller.available_rankings(request) if not choices or key not in next(zip(*choices)): raise Http404 return rcontroller.render_ranking_to_csv(request, key)
@enforce_condition(contest_exists & is_contest_basicadmin) @require_POST
[docs]def ranking_invalidate_view(request, key): rcontroller = request.contest.controller.ranking_controller() full_key = rcontroller.get_full_key(request, key) ranking = Ranking.objects.filter(key=full_key) Ranking.invalidate_queryset(ranking) return redirect('ranking', key=key)