Skip to content

Commit f3fa600

Browse files
authored
chore: url cleanup (#56)
1 parent 0bdbfe6 commit f3fa600

13 files changed

Lines changed: 98 additions & 101 deletions

File tree

seminare/content/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from seminare.content import views
44

55
urlpatterns = [
6-
path("posts/", views.PostListView.as_view(), name="post_list"),
7-
path("posts/<slug>/", views.PostDetailView.as_view(), name="post_detail"),
6+
path("prispevky/", views.PostListView.as_view(), name="post_list"),
7+
path("prispevky/<slug>/", views.PostDetailView.as_view(), name="post_detail"),
88
path("<path:slug>/", views.PageDetailView.as_view(), name="page_detail"),
99
]

seminare/content/views.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from django.contrib.sites.shortcuts import get_current_site
21
from django.http import Http404, HttpRequest, HttpResponseBase
32
from django.shortcuts import get_object_or_404, redirect
43
from django.views.generic import DetailView, ListView
@@ -28,7 +27,7 @@ def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponseBase:
2827
).first()
2928

3029
if self.page is None:
31-
if self.is_organizer:
30+
if self.is_organizer and not self.kwargs.get("slug").startswith("org/"):
3231
return redirect("org:page_create", slug=self.kwargs["slug"])
3332
raise Http404()
3433

@@ -48,13 +47,17 @@ class PostListView(ListView):
4847
paginate_by = 15
4948

5049
def get_queryset(self):
51-
site = get_current_site(self.request)
52-
return Post.objects.filter(contests__site=site)
50+
contest = get_current_contest(self.request)
51+
return Post.objects.filter(contests__id=contest.id).select_related("author")
5352

5453

5554
class PostDetailView(DetailView):
5655
template_name = "post/detail.html"
5756

5857
def get_object(self, queryset=...):
59-
site = get_current_site(self.request)
60-
return get_object_or_404(Post, slug=self.kwargs["slug"], contests__site=site)
58+
contest = get_current_contest(self.request)
59+
return get_object_or_404(
60+
Post.objects.select_related("author"),
61+
slug=self.kwargs["slug"],
62+
contests__id=contest.id,
63+
)

seminare/organizer/forms.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from django.core.validators import FileExtensionValidator
33

44
from seminare.content.models import Page, Post
5-
from seminare.contests.models import Contest
65
from seminare.problems.models import Problem, ProblemSet, Text
76
from seminare.rules import get_rule_engine_class
87
from seminare.style.forms import DateTimeInput
@@ -162,9 +161,9 @@ class Meta:
162161
"content": "Obsah",
163162
}
164163

165-
def __init__(self, *, site, **kwargs):
164+
def __init__(self, *, contest, **kwargs):
166165
super().__init__(**kwargs)
167-
self.contest = Contest.objects.filter(site=site).first()
166+
self.contest = contest
168167

169168
def clean_slug(self):
170169
slug = self.cleaned_data["slug"]

seminare/organizer/tables.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ def get_links(
6666
"Opravovanie",
6767
reverse(
6868
"org:grading_overview",
69-
args=[object.id],
69+
args=[
70+
object.problem_set.slug,
71+
object.number,
72+
],
7073
),
7174
),
7275
]
@@ -79,7 +82,7 @@ def get_links(
7982
"org:problem_update",
8083
args=[
8184
object.problem_set.slug,
82-
object.id,
85+
object.number,
8386
],
8487
),
8588
),

seminare/organizer/templates/org/grading/_form.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{# Grading form #}
2-
<form class="gap-y-4 text-sm flex-1 flex flex-col" enctype="multipart/form-data" method="post" action="{% url 'org:grading_submit' submit.submit_id %}" hx-boost="true">
2+
<form class="gap-y-4 text-sm flex-1 flex flex-col" enctype="multipart/form-data" method="post" action="{% url 'org:grading_submit' problem_set.slug problem.number submit.submit_id %}" hx-boost="true">
33
<textarea name="comment" class="input flex-1 {% if form.comment.errors %}border-red-600 placeholder-red-600{% endif %}" rows=7 placeholder="Komentár">{{ form.comment.value }}</textarea>
44

55
{% if type == 'file' %}

seminare/organizer/templates/org/grading/_overview_score.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{{ submit.score|floatformat:"g" }}
88
{% endif %}
99
<iconify-icon icon="mdi:pencil" class="text-gray-800/40 group-hover:text-gray-800"></iconify-icon>
10-
<a href="{% url "org:grading_submit" submit.submit_id %}" class="inset-0 absolute" {% if submit.scored_by %}data-tippy-content="{{ submit.scored_by.display_name }}"{% endif %}></a>
10+
<a href="{% url "org:grading_submit" problem_set.slug problem.number submit.submit_id %}" class="inset-0 absolute" {% if submit.scored_by %}data-tippy-content="{{ submit.scored_by.display_name }}"{% endif %}></a>
1111
{% else %}
1212
<span class="text-gray-400">neodovzdané</span>
1313
{% endif %}

seminare/organizer/templates/org/grading/submit.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
{% block org_body %}
88
<div class="flex w-full h-full max-h-screen">
99
<div class="border-r w-80 shrink-0 px-4 py-3 overflow-auto space-y-1" hx-boost="true">
10-
<a href="{% url 'org:grading_overview' submit.problem_id %}#user-{{ submit.enrollment.user_id }}" class="link flex items-center mb-2">
10+
<a href="{% url 'org:grading_overview' problem_set.slug problem.number %}#user-{{ submit.enrollment.user_id }}" class="link flex items-center mb-2">
1111
<iconify-icon icon="mdi:arrow-left" class="mr-1"></iconify-icon>
1212
Späť na hodnotenie úlohy
1313
</a>
1414

1515
{% for row in other_users %}
1616
{% if row.submit %}
17-
<a href="{% url 'org:grading_submit' row.submit.submit_id %}" class="block text-gray-800 px-3 py-2 hover:bg-gray-50 {% if row.user.id == submit.enrollment.user_id %}bg-gray-100 scroll-to-me{% endif %} rounded">
17+
<a href="{% url 'org:grading_submit' problem_set.slug problem.number row.submit.submit_id %}" class="block text-gray-800 px-3 py-2 hover:bg-gray-50 {% if row.user.id == submit.enrollment.user_id %}bg-gray-100 scroll-to-me{% endif %} rounded">
1818
<div class="flex items-center justify-between font-semibold">
1919
<span>{{ row.user.display_name }}</span>
2020
{% if row.submit.score is not None %}
@@ -44,9 +44,9 @@
4444
{% for osubmit in other_submits %}
4545
{% if osubmit.type == "submit" %}
4646
{% with other_submit=osubmit.submit %}
47-
<a href="{% url 'org:grading_submit' other_submit.submit_id %}" class="block text-gray-800 px-3 py-2 hover:bg-gray-50 {% if other_submit == submit %}bg-gray-100 scroll-to-me{% endif %} rounded">
47+
<a href="{% url 'org:grading_submit' problem_set.slug problem.number other_submit.submit_id %}" class="block text-gray-800 px-3 py-2 hover:bg-gray-50 {% if other_submit == submit %}bg-gray-100 scroll-to-me{% endif %} rounded">
4848
<div class="flex items-center justify-between font-semibold gap-1">
49-
<span class="text-ellipsis overflow-hidden text-sm">{{ submit.created_at }}</span>
49+
<span class="text-ellipsis overflow-hidden text-sm">{{ other_submit.created_at }}</span>
5050
<span data-submit-score="{{ other_submit.id }}"class="text-green-600 whitespace-nowrap shrink-0 tabular-nums">{% if other_submit.score is not None %}{{ other_submit.score|floatformat:"g" }} b{% endif %}</span>
5151
</div>
5252
</a>

seminare/organizer/urls.py

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,72 @@
1-
from django.urls import include, path
1+
from django.urls import path
22

33
from seminare.organizer.views import dashboard, grading, page, post, problem, problemset
44

55
app_name = "org"
66

7-
contest_patterns = [
7+
urlpatterns = [
88
path("", dashboard.ContestDashboardView.as_view(), name="contest_dashboard"),
9-
path("sets/", problemset.ProblemSetListView.as_view(), name="problemset_list"),
9+
path("kola/", problemset.ProblemSetListView.as_view(), name="problemset_list"),
1010
path(
11-
"sets/create/",
11+
"kola/vytvorit/",
1212
problemset.ProblemSetCreateView.as_view(),
1313
name="problemset_create",
1414
),
1515
path(
16-
"sets/<slug>/",
16+
"kola/<problem_set_slug>/",
1717
problemset.ProblemSetUpdateView.as_view(),
1818
name="problemset_update",
1919
),
2020
path(
21-
"grading/problem/<int:problem_id>/",
21+
"kola/<problem_set_slug>/ulohy/<int:number>/opravovanie/",
2222
grading.GradingOverviewView.as_view(),
2323
name="grading_overview",
2424
),
2525
path(
26-
"grading/problem/<int:problem_id>/bulk/",
26+
"kola/<problem_set_slug>/ulohy/<int:number>/opravovanie/hromadne/",
2727
grading.BulkGradingView.as_view(),
2828
name="bulk_grading",
2929
),
3030
path(
31-
"grading/problem/<int:problem_id>/bulk/download/",
31+
"kola/<problem_set_slug>/ulohy/<int:number>/opravovanie/hromadne/stiahnut/",
3232
grading.BulkGradingDownloadView.as_view(),
3333
name="bulk_grading_download",
3434
),
3535
path(
36-
"grading/submit/<submit_id:submit_id>/",
36+
"kola/<problem_set_slug>/ulohy/<int:number>/opravovanie/<submit_id:submit_id>/",
3737
grading.GradingSubmitView.as_view(),
3838
name="grading_submit",
3939
),
4040
path(
41-
"sets/<problem_set_slug>/problems/",
41+
"kola/<problem_set_slug>/ulohy/",
4242
problem.ProblemListView.as_view(),
4343
name="problem_list",
4444
),
4545
path(
46-
"sets/<problem_set_slug>/problems/<int:problem_id>/",
46+
"kola/<problem_set_slug>/ulohy/<int:number>/",
4747
problem.ProblemUpdateView.as_view(),
4848
name="problem_update",
4949
),
5050
path(
51-
"sets/<problem_set_slug>/problems/create/",
51+
"kola/<problem_set_slug>/ulohy/vytvorit/",
5252
problem.ProblemCreateView.as_view(),
5353
name="problem_create",
5454
),
55-
path("posts/", post.PostListView.as_view(), name="post_list"),
56-
path("posts/<int:pk>/", post.PostUpdateView.as_view(), name="post_update"),
57-
path("posts/<int:pk>/delete/", post.PostDeleteView.as_view(), name="post_delete"),
58-
path("posts/create/", post.PostCreateView.as_view(), name="post_create"),
59-
]
60-
61-
62-
urlpatterns = [
63-
path("contests/", include(contest_patterns)),
64-
path("pages/", page.PageListView.as_view(), name="page_list"),
65-
path("pages/<int:pk>/", page.PageUpdateView.as_view(), name="page_update"),
66-
path("pages/<int:pk>/delete/", page.PageDeleteView.as_view(), name="page_delete"),
67-
path("pages/create/", page.PageCreateView.as_view(), name="page_create"),
55+
path("prispevky/", post.PostListView.as_view(), name="post_list"),
56+
path("prispevky/<int:pk>/", post.PostUpdateView.as_view(), name="post_update"),
57+
path(
58+
"prispevky/<int:pk>/vymazat/", post.PostDeleteView.as_view(), name="post_delete"
59+
),
60+
path("prispevky/vytvorit/", post.PostCreateView.as_view(), name="post_create"),
61+
path("stranky/", page.PageListView.as_view(), name="page_list"),
62+
path("stranky/<int:pk>/", page.PageUpdateView.as_view(), name="page_update"),
63+
path(
64+
"stranky/<int:pk>/vymazat/", page.PageDeleteView.as_view(), name="page_delete"
65+
),
66+
path("stranky/vytvorit/", page.PageCreateView.as_view(), name="page_create"),
6867
path(
69-
"pages/create/<path:slug>/", page.PageCreateView.as_view(), name="page_create"
68+
"stranky/vytvorit/<path:slug>/",
69+
page.PageCreateView.as_view(),
70+
name="page_create",
7071
),
7172
]

seminare/organizer/views/__init__.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from seminare.contests.models import Contest
88
from seminare.contests.utils import get_current_contest
9-
from seminare.problems.models import ProblemSet
9+
from seminare.problems.models import Problem, ProblemSet
1010
from seminare.submits.models import BaseSubmit
1111

1212

@@ -37,21 +37,25 @@ def get_context_data(self, **kwargs):
3737
return ctx
3838

3939

40-
class WithProblemSet(MixinProtocol):
40+
class WithProblemSet(WithContest, MixinProtocol):
4141
@cached_property
4242
def problem_set(self) -> ProblemSet:
43-
return get_object_or_404(ProblemSet, slug=self.kwargs["problem_set_slug"])
43+
return get_object_or_404(
44+
ProblemSet, slug=self.kwargs["problem_set_slug"], contest=self.contest
45+
)
4446

4547
def get_context_data(self, **kwargs):
4648
ctx = super().get_context_data(**kwargs)
4749
ctx["problem_set"] = self.problem_set
4850
return ctx
4951

5052

51-
class WithProblem(MixinProtocol):
53+
class WithProblem(WithProblemSet, MixinProtocol):
5254
@cached_property
53-
def problem(self) -> ProblemSet:
54-
return get_object_or_404(ProblemSet, id=self.kwargs["problem_id"])
55+
def problem(self) -> Problem:
56+
return get_object_or_404(
57+
Problem, problem_set=self.problem_set, number=self.kwargs["number"]
58+
)
5559

5660
def get_context_data(self, **kwargs):
5761
ctx = super().get_context_data(**kwargs)

seminare/organizer/views/grading.py

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from django.core.files.base import ContentFile
99
from django.db.models.fields.files import FieldFile
1010
from django.http import FileResponse, HttpResponseRedirect
11-
from django.shortcuts import get_object_or_404
1211
from django.template.defaultfilters import slugify
1312
from django.urls import reverse
1413
from django.utils.functional import cached_property
@@ -19,20 +18,17 @@
1918
from seminare.organizer.views import (
2019
MixinProtocol,
2120
WithBreadcrumbs,
22-
WithContest,
21+
WithProblem,
2322
WithSubmit,
2423
)
2524
from seminare.organizer.views.generic import GenericFormView
26-
from seminare.problems.models import Problem
2725
from seminare.rules import RuleEngine
2826
from seminare.submits.models import BaseSubmit, FileSubmit, JudgeSubmit, TextSubmit
2927
from seminare.users.mixins.permissions import ContestOrganizerRequired
3028
from seminare.users.models import Enrollment
3129

3230

33-
class WithSubmitList(WithContest, MixinProtocol):
34-
problem: Problem | cached_property
35-
31+
class WithSubmitList(WithProblem, MixinProtocol):
3632
@cached_property
3733
def rule_engine(self) -> RuleEngine:
3834
return self.problem.problem_set.get_rule_engine()
@@ -80,16 +76,13 @@ def get_users_with_submits(self, limit_types=None):
8076

8177

8278
class GradingOverviewView(
83-
ContestOrganizerRequired, WithSubmitList, WithBreadcrumbs, TemplateView
79+
ContestOrganizerRequired,
80+
WithSubmitList,
81+
WithBreadcrumbs,
82+
TemplateView,
8483
):
8584
template_name = "org/grading/overview.html"
8685

87-
@cached_property
88-
def problem(self):
89-
return get_object_or_404(
90-
Problem, id=self.kwargs["problem_id"], problem_set__contest=self.contest
91-
)
92-
9386
def get_context_data(self, **kwargs):
9487
ctx = super().get_context_data(**kwargs)
9588
ctx["problem"] = self.problem
@@ -99,7 +92,10 @@ def get_context_data(self, **kwargs):
9992
"default",
10093
"mdi:human-queue",
10194
"Hromadné opravovanie",
102-
reverse("org:bulk_grading", args=[self.problem.id]),
95+
reverse(
96+
"org:bulk_grading",
97+
args=[self.problem_set.slug, self.problem.number],
98+
),
10399
)
104100
]
105101
return ctx
@@ -187,12 +183,6 @@ class BulkGradingView(ContestOrganizerRequired, WithSubmitList, GenericFormView)
187183
form_header_template = "org/grading/_bulk_header.html"
188184
form_multipart = True
189185

190-
@cached_property
191-
def problem(self):
192-
return get_object_or_404(
193-
Problem, id=self.kwargs["problem_id"], problem_set__contest=self.contest
194-
)
195-
196186
def form_valid(self, form):
197187
enrollments = self.rule_engine.get_enrollments().select_related("user")
198188

@@ -262,12 +252,17 @@ def get_form_links(self):
262252
"default",
263253
"mdi:download",
264254
"Stiahnuť ZIP na opravovanie",
265-
reverse("org:bulk_grading_download", args=[self.kwargs["problem_id"]]),
255+
reverse(
256+
"org:bulk_grading_download",
257+
args=[self.problem_set.slug, self.problem.number],
258+
),
266259
)
267260
]
268261

269262
def get_success_url(self):
270-
return reverse("org:grading_overview", args=[self.kwargs["problem_id"]])
263+
return reverse(
264+
"org:grading_overview", args=[self.problem_set.slug, self.problem.number]
265+
)
271266

272267
def get_breadcrumbs(self):
273268
return [
@@ -281,18 +276,18 @@ def get_breadcrumbs(self):
281276
),
282277
),
283278
(self.problem, ""),
284-
("Opravovanie", reverse("org:grading_overview", args=[self.problem.id])),
279+
(
280+
"Opravovanie",
281+
reverse(
282+
"org:grading_overview",
283+
args=[self.problem_set.slug, self.problem.number],
284+
),
285+
),
285286
("Hromadné opravovanie", ""),
286287
]
287288

288289

289290
class BulkGradingDownloadView(ContestOrganizerRequired, WithSubmitList, View):
290-
@cached_property
291-
def problem(self):
292-
return get_object_or_404(
293-
Problem, id=self.kwargs["problem_id"], problem_set__contest=self.contest
294-
)
295-
296291
def get(self, request, *args, **kwargs):
297292
enrollments = self.rule_engine.get_enrollments().select_related("user")
298293
enrollments_by_id = {enrollment.id: enrollment for enrollment in enrollments}

0 commit comments

Comments
 (0)