feat(event): option to disable an event

This commit is contained in:
2026-10-16 00:18:36 +02:00
parent b837abdba0
commit 15ab9a14ac
8 changed files with 89 additions and 9 deletions
+3 -1
View File
@@ -5,7 +5,9 @@ from .models import Event
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
list_display = ["name", "path", "created_at"]
list_display = ["name", "path", "is_available", "created_at"]
list_editable = ["is_available"]
list_filter = ["is_available"]
search_fields = ["name", "path"]
prepopulated_fields = {"path": ("name",)}
readonly_fields = ["created_at", "updated_at"]
+4 -1
View File
@@ -22,6 +22,9 @@ class EventContextMiddleware:
def process_view(self, request, view_func, view_args, view_kwargs):
event_path = view_kwargs.get("event_path")
if event_path:
request.event = get_object_or_404(Event, path=event_path)
request.event = get_object_or_404(
Event.objects.available_to(getattr(request, "user", None)),
path=event_path,
)
current_event.set(request.event)
return None
@@ -0,0 +1,17 @@
# Generated by Django 6.0.5 on 2026-10-15 22:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("events", "0002_seed_polylan_43"),
]
operations = [
migrations.AddField(
model_name="event",
name="is_available",
field=models.BooleanField(default=True),
),
]
+12
View File
@@ -14,9 +14,21 @@ class BaseModel(models.Model):
abstract = True
class EventQuerySet(models.QuerySet):
def available_to(self, user):
"""Unavailable events are hidden from everyone but staff, so they can
still be prepared before being opened up."""
if user is not None and user.is_staff:
return self
return self.filter(is_available=True)
class Event(BaseModel):
name = models.CharField(max_length=255)
path = models.SlugField(max_length=100, unique=True)
is_available = models.BooleanField(default=True)
objects = EventQuerySet.as_manager()
def __str__(self) -> str:
return self.name
+40
View File
@@ -1,3 +1,5 @@
from datetime import timedelta
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase
@@ -32,3 +34,41 @@ class EventScopedManagerTests(TestCase):
current_event.reset(token)
self.assertEqual(results, [self.submission_a])
class EventAvailabilityTests(TestCase):
def setUp(self):
from accounts.models import CustomUser
self.hidden = Event.objects.create(
name="Hidden", path="hidden", is_available=False
)
self.user = CustomUser.objects.create_user(username="user", password="x")
self.staff = CustomUser.objects.create_user(
username="staff", password="x", is_staff=True
)
def test_unavailable_event_is_404_for_regular_user(self):
self.client.force_login(self.user)
response = self.client.get(f"/{self.hidden.path}/market")
self.assertEqual(response.status_code, 404)
def test_unavailable_event_is_visible_to_staff(self):
self.client.force_login(self.staff)
response = self.client.get(f"/{self.hidden.path}/market")
self.assertEqual(response.status_code, 200)
def test_available_to_filters_for_regular_user_only(self):
self.assertNotIn(self.hidden, Event.objects.available_to(self.user))
self.assertIn(self.hidden, Event.objects.available_to(self.staff))
def test_home_prefers_available_event_for_staff(self):
available = Event.objects.create(name="Open", path="open")
Event.objects.filter(pk=self.hidden.pk).update(
created_at=available.created_at + timedelta(days=1)
)
self.client.force_login(self.staff)
response = self.client.get("/")
self.assertRedirects(
response, f"/{available.path}/", fetch_redirect_response=False
)