mirror of
https://gitlab.com/megazordpobeda/DataRush.git
synced 2026-05-22 22:07:10 +00:00
add leaderboard view to admin panel
This commit is contained in:
@@ -1,7 +1,15 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.urls import path, reverse
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.template.response import TemplateResponse
|
||||||
|
from django.db.models import Count, Q, Sum
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.html import format_html
|
||||||
|
|
||||||
|
from apps.user.models import User
|
||||||
from apps.competition.models import Competition
|
from apps.competition.models import Competition
|
||||||
from apps.task.admin import CompetitionTaskInline
|
from apps.task.admin import CompetitionTaskInline
|
||||||
|
from apps.task.models import CompetitionTaskSubmission, CompetitionTask
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Competition)
|
@admin.register(Competition)
|
||||||
@@ -11,6 +19,7 @@ class CompetitionAdmin(admin.ModelAdmin):
|
|||||||
"title",
|
"title",
|
||||||
"end_date",
|
"end_date",
|
||||||
"type",
|
"type",
|
||||||
|
"view_leaderboard",
|
||||||
)
|
)
|
||||||
search_fields = (
|
search_fields = (
|
||||||
"title",
|
"title",
|
||||||
@@ -21,3 +30,57 @@ class CompetitionAdmin(admin.ModelAdmin):
|
|||||||
"participation_type",
|
"participation_type",
|
||||||
)
|
)
|
||||||
inlines = [CompetitionTaskInline]
|
inlines = [CompetitionTaskInline]
|
||||||
|
|
||||||
|
def get_urls(self):
|
||||||
|
urls = super().get_urls()
|
||||||
|
custom_urls = [
|
||||||
|
path('leaderboard/', self.admin_site.admin_view(self.leaderboard_view), name='competition_leaderboard'),
|
||||||
|
path('<uuid:competition_id>/leaderboard/', self.admin_site.admin_view(self.competition_leaderboard_view),
|
||||||
|
name='competition_specific_leaderboard'),
|
||||||
|
]
|
||||||
|
return custom_urls + urls
|
||||||
|
|
||||||
|
def view_leaderboard(self, obj):
|
||||||
|
url = reverse('admin:competition_specific_leaderboard', args=[obj.id])
|
||||||
|
return format_html('<a href="{}">лидерборд</a>', url)
|
||||||
|
|
||||||
|
view_leaderboard.short_description = "Лидерборд"
|
||||||
|
view_leaderboard.allow_tags = True
|
||||||
|
|
||||||
|
def competition_leaderboard_view(self, request, competition_id):
|
||||||
|
competition = get_object_or_404(Competition, id=competition_id)
|
||||||
|
|
||||||
|
competition_tasks = CompetitionTask.objects.filter(competition=competition)
|
||||||
|
|
||||||
|
leaderboard = User.objects.annotate(
|
||||||
|
total_score=Sum(
|
||||||
|
'competitiontasksubmission__earned_points',
|
||||||
|
filter=Q(
|
||||||
|
competitiontasksubmission__status='checked',
|
||||||
|
competitiontasksubmission__task__in=competition_tasks
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).exclude(total_score__isnull=True).order_by('-total_score')[:20]
|
||||||
|
|
||||||
|
context = dict(
|
||||||
|
self.admin_site.each_context(request),
|
||||||
|
title=f"Лидерборд для {competition.title}",
|
||||||
|
leaderboard=leaderboard,
|
||||||
|
competition=competition,
|
||||||
|
)
|
||||||
|
return TemplateResponse(request, "admin/competition_leaderboard.html", context)
|
||||||
|
|
||||||
|
def leaderboard_view(self, request):
|
||||||
|
leaderboard = User.objects.annotate(
|
||||||
|
total_score=Sum(
|
||||||
|
'competitiontasksubmission__earned_points',
|
||||||
|
filter=Q(competitiontasksubmission__status='checked')
|
||||||
|
)
|
||||||
|
).exclude(total_score__isnull=True).order_by('-total_score')[:20]
|
||||||
|
|
||||||
|
context = dict(
|
||||||
|
self.admin_site.each_context(request),
|
||||||
|
title="Global Competition Leaderboard",
|
||||||
|
leaderboard=leaderboard,
|
||||||
|
)
|
||||||
|
return TemplateResponse(request, "admin/competition_leaderboard.html", context)
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ SESSION_SERIALIZER = "django.contrib.sessions.serializers.JSONSerializer"
|
|||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
"DIRS": [],
|
"DIRS": [BASE_DIR / "templates"],
|
||||||
"APP_DIRS": True,
|
"APP_DIRS": True,
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
"autoescape": True,
|
"autoescape": True,
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
{% extends "admin/base_site.html" %}
|
||||||
|
{% load i18n admin_urls %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
<div class="breadcrumbs">
|
||||||
|
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||||
|
› <a href="{% url 'admin:app_list' app_label='competition' %}">Соревнования</a>
|
||||||
|
{% if competition %}
|
||||||
|
› <a href="{% url 'admin:competition_competition_change' competition.id %}">{{ competition.title }}</a>
|
||||||
|
{% endif %}
|
||||||
|
› Лидерборд
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="content-main">
|
||||||
|
<h1>{% if competition %}Лидерборд: {{ competition.title }}{% else %}Лидерборд соревнования{% endif %}</h1>
|
||||||
|
<div class="module">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Ранг</th>
|
||||||
|
<th>Участник</th>
|
||||||
|
<th>Баллы</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for user in leaderboard %}
|
||||||
|
<tr class="{% cycle 'row1' 'row2' %}">
|
||||||
|
<td>{{ forloop.counter }}</td>
|
||||||
|
<td>{{ user.username }}</td>
|
||||||
|
<td>{{ user.total_score|default:0 }}</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">Пока что нет посылок</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user