We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add http endpoint for the next event 
### Is your feature request related to a problem? Please describe.
We want to use a dns redirect to redirect to the first upcoming Thalia event. 

### Describe the solution you'd like
An endpoint (like /events/next) that redicects to the next Thalia event 
### Motivation
We want to setup a domain (sog.je) that redirects to this 

### Describe alternatives you've considered
Static html host that uses javascriot, but this would require using additional resources 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `website/events/views.py`
Content:
```
1 """Views provided by the events package."""
2 
3 from django.contrib import messages
4 from django.contrib.auth.decorators import login_required
5 from django.shortcuts import get_object_or_404, redirect
6 from django.utils import timezone
7 from django.utils.decorators import method_decorator
8 from django.utils.translation import gettext_lazy as _
9 from django.views import View
10 from django.views.generic import DetailView, FormView, TemplateView
11 
12 from events import services
13 from events.exceptions import RegistrationError
14 from events.models import categories
15 from events.services import is_user_registered
16 from payments.models import Payment
17 
18 from .forms import FieldsForm
19 from .models import Event, EventRegistration
20 
21 
22 class EventIndex(TemplateView):
23     """Render the events calendar overview."""
24 
25     template_name = "events/index.html"
26 
27     def get_context_data(self, **kwargs):
28         context = super().get_context_data(**kwargs)
29 
30         upcoming_activity = (
31             Event.objects.filter(published=True, end__gte=timezone.now())
32             .order_by("end")
33             .first()
34         )
35         context["upcoming_activity"] = upcoming_activity
36 
37         return context
38 
39 
40 class EventDetail(DetailView):
41     """Render a single event detail page."""
42 
43     model = Event
44     queryset = Event.objects.filter(published=True)
45     template_name = "events/event.html"
46     context_object_name = "event"
47 
48     def get_context_data(self, **kwargs):
49         context = super().get_context_data(**kwargs)
50         context["user"] = self.request.user
51         context["payment_method_tpay"] = Payment.TPAY
52 
53         event = context["event"]
54         if event.max_participants:
55             perc = 100.0 * len(event.participants) / event.max_participants
56             context["registration_percentage"] = perc
57 
58         try:
59             context["registration"] = EventRegistration.objects.get(
60                 event=event, member=self.request.member
61             )
62         except (EventRegistration.DoesNotExist, TypeError):
63             pass
64 
65         registration_status = services.registration_status(
66             event, context.get("registration"), self.request.member
67         )
68         context["registration_status"] = services.registration_status_string(
69             registration_status, event, context.get("registration")
70         )
71 
72         context["show_cancel_status"] = services.show_cancel_status(registration_status)
73         if context["show_cancel_status"]:
74             cancel_status = services.cancel_status(event, context.get("registration"))
75             context["cancel_info"] = services.cancel_info_string(
76                 event, cancel_status, registration_status
77             )
78 
79         context["permissions"] = services.event_permissions(self.request.member, event)
80 
81         context["date_now"] = timezone.now()
82 
83         context["slide_size"] = "slide"
84 
85         context["participants"] = event.participants.select_related(
86             "member", "member__profile"
87         )
88 
89         return context
90 
91 
92 class AlumniEventsView(TemplateView):
93     """Render the alumni events page."""
94 
95     template_name = "events/alumni.html"
96 
97     def get_context_data(self, **kwargs):
98         context = super().get_context_data(**kwargs)
99 
100         events = Event.objects.filter(
101             published=True, category=categories.CATEGORY_ALUMNI, end__gte=timezone.now()
102         ).order_by("end")[:3]
103         context["events"] = events
104 
105         return context
106 
107 
108 @method_decorator(login_required, name="dispatch")
109 class EventRegisterView(View):
110     """Define a view that allows the user to register for an event using a POST request.
111 
112     The user should be authenticated.
113     """
114 
115     def get(self, request, *args, **kwargs):
116         return redirect("events:event", pk=kwargs["pk"])
117 
118     def post(self, request, *args, **kwargs):
119         event = get_object_or_404(Event, pk=kwargs["pk"])
120         try:
121             services.create_registration(request.member, event)
122 
123             if event.has_fields:
124                 return redirect("events:registration", event.pk)
125 
126             messages.success(request, _("Registration successful."))
127         except RegistrationError as e:
128             messages.error(request, e)
129 
130         return redirect(event)
131 
132 
133 @method_decorator(login_required, name="dispatch")
134 class EventCancelView(View):
135     """Define a view that allows the user to cancel their event registration using a POST request.
136 
137     The user should be authenticated.
138     """
139 
140     def get(self, request, *args, **kwargs):
141         return redirect("events:event", pk=kwargs["pk"])
142 
143     def post(self, request, *args, **kwargs):
144         event = get_object_or_404(Event, pk=kwargs["pk"])
145         try:
146             services.cancel_registration(request.member, event)
147             messages.success(request, _("Registration successfully cancelled."))
148         except RegistrationError as e:
149             messages.error(request, e)
150 
151         return redirect(event)
152 
153 
154 @method_decorator(login_required, name="dispatch")
155 class RegistrationView(FormView):
156     """Render a form that allows the user to change the details of their registration.
157 
158     The user should be authenticated.
159     """
160 
161     form_class = FieldsForm
162     template_name = "events/registration.html"
163     event = None
164 
165     def get_context_data(self, **kwargs):
166         context = super().get_context_data(**kwargs)
167         context["event"] = self.event
168         return context
169 
170     def get_form_kwargs(self):
171         kwargs = super().get_form_kwargs()
172         kwargs["fields"] = services.registration_fields(
173             self.request, self.request.member, self.event
174         )
175         return kwargs
176 
177     def form_valid(self, form):
178         values = form.field_values()
179         try:
180             services.update_registration(
181                 self.request.member, self.event, field_values=values
182             )
183             messages.success(self.request, _("Registration successfully saved."))
184             return redirect(self.event)
185         except RegistrationError as e:
186             messages.error(self.request, e)
187             return self.render_to_response(self.get_context_data(form=form))
188 
189     def dispatch(self, request, *args, **kwargs):
190         self.event = get_object_or_404(Event, pk=self.kwargs["pk"])
191         try:
192             if self.event.has_fields:
193                 return super().dispatch(request, *args, **kwargs)
194         except RegistrationError:
195             pass
196         return redirect(self.event)
197 
198 
199 @method_decorator(login_required, name="dispatch")
200 class MarkPresentView(View):
201     """A view that allows uses to mark their presence at an event using a secret token."""
202 
203     def get(self, request, *args, **kwargs):
204         """Mark a user as present.
205 
206         Checks if the url is correct, the event has not ended yet, and the user is registered.
207         """
208         event = get_object_or_404(Event, pk=kwargs["pk"])
209         if kwargs["token"] != event.mark_present_url_token:
210             messages.error(request, _("Invalid url."))
211         elif not request.member or not is_user_registered(request.member, event):
212             messages.error(request, _("You are not registered for this event."))
213         else:
214             registration = event.registrations.get(
215                 member=request.member, date_cancelled=None
216             )
217 
218             if registration.present:
219                 messages.info(request, _("You were already marked as present."))
220             elif event.end < timezone.now():
221                 messages.error(request, _("This event has already ended."))
222             else:
223                 registration.present = True
224                 registration.save()
225                 messages.success(request, _("You have been marked as present."))
226 
227         return redirect(event)
228
```

Path: `website/events/urls.py`
Content:
```
1 """Routes defined by the events package."""
2 from django.urls import include, path
3 
4 from events.feeds import EventFeed
5 from events.views import (
6     AlumniEventsView,
7     EventCancelView,
8     EventDetail,
9     EventIndex,
10     EventRegisterView,
11     MarkPresentView,
12     RegistrationView,
13 )
14 
15 app_name = "events"
16 
17 urlpatterns = [
18     path(
19         "events/",
20         include(
21             [
22                 path("<int:pk>/", EventDetail.as_view(), name="event"),
23                 path("<slug:slug>/", EventDetail.as_view(), name="event"),
24                 path(
25                     "<int:pk>/registration/register/",
26                     EventRegisterView.as_view(),
27                     name="register",
28                 ),
29                 path(
30                     "<int:pk>/registration/cancel/",
31                     EventCancelView.as_view(),
32                     name="cancel",
33                 ),
34                 path(
35                     "<int:pk>/mark-present/<uuid:token>/",
36                     MarkPresentView.as_view(),
37                     name="mark-present",
38                 ),
39                 path(
40                     "<int:pk>/registration/",
41                     RegistrationView.as_view(),
42                     name="registration",
43                 ),
44                 path("", EventIndex.as_view(), name="index"),
45                 path("ical/nl.ics", EventFeed(), name="ical-nl"),
46                 path("ical/en.ics", EventFeed(), name="ical-en"),
47             ]
48         ),
49     ),
50     path("association/alumni/", AlumniEventsView.as_view(), name="alumni"),
51 ]
52
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/website/events/urls.py b/website/events/urls.py
--- a/website/events/urls.py
+++ b/website/events/urls.py
@@ -9,6 +9,7 @@
     EventIndex,
     EventRegisterView,
     MarkPresentView,
+    NextEventView,
     RegistrationView,
 )
 
@@ -20,6 +21,7 @@
         include(
             [
                 path("<int:pk>/", EventDetail.as_view(), name="event"),
+                path("next/", NextEventView.as_view(), name="next"),
                 path("<slug:slug>/", EventDetail.as_view(), name="event"),
                 path(
                     "<int:pk>/registration/register/",
diff --git a/website/events/views.py b/website/events/views.py
--- a/website/events/views.py
+++ b/website/events/views.py
@@ -2,6 +2,7 @@
 
 from django.contrib import messages
 from django.contrib.auth.decorators import login_required
+from django.http import Http404
 from django.shortcuts import get_object_or_404, redirect
 from django.utils import timezone
 from django.utils.decorators import method_decorator
@@ -225,3 +226,20 @@
                 messages.success(request, _("You have been marked as present."))
 
         return redirect(event)
+
+
+class NextEventView(View):
+    def get(self, request, *args, **kwargs):
+        """HTTP redirect to the next event.
+
+        Checks if there is an upcoming event. Raise a 404 if none exists.
+        """
+        upcoming_activity = (
+            Event.objects.filter(published=True, end__gte=timezone.now())
+            .order_by("end")
+            .first()
+        )
+        if not upcoming_activity:
+            raise Http404("There is no upcoming event.")
+
+        return redirect(upcoming_activity)

{"golden_diff": "diff --git a/website/events/urls.py b/website/events/urls.py\n--- a/website/events/urls.py\n+++ b/website/events/urls.py\n@@ -9,6 +9,7 @@\n     EventIndex,\n     EventRegisterView,\n     MarkPresentView,\n+    NextEventView,\n     RegistrationView,\n )\n \n@@ -20,6 +21,7 @@\n         include(\n             [\n                 path(\"<int:pk>/\", EventDetail.as_view(), name=\"event\"),\n+                path(\"next/\", NextEventView.as_view(), name=\"next\"),\n                 path(\"<slug:slug>/\", EventDetail.as_view(), name=\"event\"),\n                 path(\n                     \"<int:pk>/registration/register/\",\ndiff --git a/website/events/views.py b/website/events/views.py\n--- a/website/events/views.py\n+++ b/website/events/views.py\n@@ -2,6 +2,7 @@\n \n from django.contrib import messages\n from django.contrib.auth.decorators import login_required\n+from django.http import Http404\n from django.shortcuts import get_object_or_404, redirect\n from django.utils import timezone\n from django.utils.decorators import method_decorator\n@@ -225,3 +226,20 @@\n                 messages.success(request, _(\"You have been marked as present.\"))\n \n         return redirect(event)\n+\n+\n+class NextEventView(View):\n+    def get(self, request, *args, **kwargs):\n+        \"\"\"HTTP redirect to the next event.\n+\n+        Checks if there is an upcoming event. Raise a 404 if none exists.\n+        \"\"\"\n+        upcoming_activity = (\n+            Event.objects.filter(published=True, end__gte=timezone.now())\n+            .order_by(\"end\")\n+            .first()\n+        )\n+        if not upcoming_activity:\n+            raise Http404(\"There is no upcoming event.\")\n+\n+        return redirect(upcoming_activity)\n", "issue": "Add http endpoint for the next event \n### Is your feature request related to a problem? Please describe.\r\nWe want to use a dns redirect to redirect to the first upcoming Thalia event. \r\n\r\n### Describe the solution you'd like\r\nAn endpoint (like /events/next) that redicects to the next Thalia event \r\n### Motivation\r\nWe want to setup a domain (sog.je) that redirects to this \r\n\r\n### Describe alternatives you've considered\r\nStatic html host that uses javascriot, but this would require using additional resources \n", "before_files": [{"content": "\"\"\"Views provided by the events package.\"\"\"\n\nfrom django.contrib import messages\nfrom django.contrib.auth.decorators import login_required\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils import timezone\nfrom django.utils.decorators import method_decorator\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views import View\nfrom django.views.generic import DetailView, FormView, TemplateView\n\nfrom events import services\nfrom events.exceptions import RegistrationError\nfrom events.models import categories\nfrom events.services import is_user_registered\nfrom payments.models import Payment\n\nfrom .forms import FieldsForm\nfrom .models import Event, EventRegistration\n\n\nclass EventIndex(TemplateView):\n    \"\"\"Render the events calendar overview.\"\"\"\n\n    template_name = \"events/index.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        upcoming_activity = (\n            Event.objects.filter(published=True, end__gte=timezone.now())\n            .order_by(\"end\")\n            .first()\n        )\n        context[\"upcoming_activity\"] = upcoming_activity\n\n        return context\n\n\nclass EventDetail(DetailView):\n    \"\"\"Render a single event detail page.\"\"\"\n\n    model = Event\n    queryset = Event.objects.filter(published=True)\n    template_name = \"events/event.html\"\n    context_object_name = \"event\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"user\"] = self.request.user\n        context[\"payment_method_tpay\"] = Payment.TPAY\n\n        event = context[\"event\"]\n        if event.max_participants:\n            perc = 100.0 * len(event.participants) / event.max_participants\n            context[\"registration_percentage\"] = perc\n\n        try:\n            context[\"registration\"] = EventRegistration.objects.get(\n                event=event, member=self.request.member\n            )\n        except (EventRegistration.DoesNotExist, TypeError):\n            pass\n\n        registration_status = services.registration_status(\n            event, context.get(\"registration\"), self.request.member\n        )\n        context[\"registration_status\"] = services.registration_status_string(\n            registration_status, event, context.get(\"registration\")\n        )\n\n        context[\"show_cancel_status\"] = services.show_cancel_status(registration_status)\n        if context[\"show_cancel_status\"]:\n            cancel_status = services.cancel_status(event, context.get(\"registration\"))\n            context[\"cancel_info\"] = services.cancel_info_string(\n                event, cancel_status, registration_status\n            )\n\n        context[\"permissions\"] = services.event_permissions(self.request.member, event)\n\n        context[\"date_now\"] = timezone.now()\n\n        context[\"slide_size\"] = \"slide\"\n\n        context[\"participants\"] = event.participants.select_related(\n            \"member\", \"member__profile\"\n        )\n\n        return context\n\n\nclass AlumniEventsView(TemplateView):\n    \"\"\"Render the alumni events page.\"\"\"\n\n    template_name = \"events/alumni.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        events = Event.objects.filter(\n            published=True, category=categories.CATEGORY_ALUMNI, end__gte=timezone.now()\n        ).order_by(\"end\")[:3]\n        context[\"events\"] = events\n\n        return context\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass EventRegisterView(View):\n    \"\"\"Define a view that allows the user to register for an event using a POST request.\n\n    The user should be authenticated.\n    \"\"\"\n\n    def get(self, request, *args, **kwargs):\n        return redirect(\"events:event\", pk=kwargs[\"pk\"])\n\n    def post(self, request, *args, **kwargs):\n        event = get_object_or_404(Event, pk=kwargs[\"pk\"])\n        try:\n            services.create_registration(request.member, event)\n\n            if event.has_fields:\n                return redirect(\"events:registration\", event.pk)\n\n            messages.success(request, _(\"Registration successful.\"))\n        except RegistrationError as e:\n            messages.error(request, e)\n\n        return redirect(event)\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass EventCancelView(View):\n    \"\"\"Define a view that allows the user to cancel their event registration using a POST request.\n\n    The user should be authenticated.\n    \"\"\"\n\n    def get(self, request, *args, **kwargs):\n        return redirect(\"events:event\", pk=kwargs[\"pk\"])\n\n    def post(self, request, *args, **kwargs):\n        event = get_object_or_404(Event, pk=kwargs[\"pk\"])\n        try:\n            services.cancel_registration(request.member, event)\n            messages.success(request, _(\"Registration successfully cancelled.\"))\n        except RegistrationError as e:\n            messages.error(request, e)\n\n        return redirect(event)\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass RegistrationView(FormView):\n    \"\"\"Render a form that allows the user to change the details of their registration.\n\n    The user should be authenticated.\n    \"\"\"\n\n    form_class = FieldsForm\n    template_name = \"events/registration.html\"\n    event = None\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"event\"] = self.event\n        return context\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"fields\"] = services.registration_fields(\n            self.request, self.request.member, self.event\n        )\n        return kwargs\n\n    def form_valid(self, form):\n        values = form.field_values()\n        try:\n            services.update_registration(\n                self.request.member, self.event, field_values=values\n            )\n            messages.success(self.request, _(\"Registration successfully saved.\"))\n            return redirect(self.event)\n        except RegistrationError as e:\n            messages.error(self.request, e)\n            return self.render_to_response(self.get_context_data(form=form))\n\n    def dispatch(self, request, *args, **kwargs):\n        self.event = get_object_or_404(Event, pk=self.kwargs[\"pk\"])\n        try:\n            if self.event.has_fields:\n                return super().dispatch(request, *args, **kwargs)\n        except RegistrationError:\n            pass\n        return redirect(self.event)\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass MarkPresentView(View):\n    \"\"\"A view that allows uses to mark their presence at an event using a secret token.\"\"\"\n\n    def get(self, request, *args, **kwargs):\n        \"\"\"Mark a user as present.\n\n        Checks if the url is correct, the event has not ended yet, and the user is registered.\n        \"\"\"\n        event = get_object_or_404(Event, pk=kwargs[\"pk\"])\n        if kwargs[\"token\"] != event.mark_present_url_token:\n            messages.error(request, _(\"Invalid url.\"))\n        elif not request.member or not is_user_registered(request.member, event):\n            messages.error(request, _(\"You are not registered for this event.\"))\n        else:\n            registration = event.registrations.get(\n                member=request.member, date_cancelled=None\n            )\n\n            if registration.present:\n                messages.info(request, _(\"You were already marked as present.\"))\n            elif event.end < timezone.now():\n                messages.error(request, _(\"This event has already ended.\"))\n            else:\n                registration.present = True\n                registration.save()\n                messages.success(request, _(\"You have been marked as present.\"))\n\n        return redirect(event)\n", "path": "website/events/views.py"}, {"content": "\"\"\"Routes defined by the events package.\"\"\"\nfrom django.urls import include, path\n\nfrom events.feeds import EventFeed\nfrom events.views import (\n    AlumniEventsView,\n    EventCancelView,\n    EventDetail,\n    EventIndex,\n    EventRegisterView,\n    MarkPresentView,\n    RegistrationView,\n)\n\napp_name = \"events\"\n\nurlpatterns = [\n    path(\n        \"events/\",\n        include(\n            [\n                path(\"<int:pk>/\", EventDetail.as_view(), name=\"event\"),\n                path(\"<slug:slug>/\", EventDetail.as_view(), name=\"event\"),\n                path(\n                    \"<int:pk>/registration/register/\",\n                    EventRegisterView.as_view(),\n                    name=\"register\",\n                ),\n                path(\n                    \"<int:pk>/registration/cancel/\",\n                    EventCancelView.as_view(),\n                    name=\"cancel\",\n                ),\n                path(\n                    \"<int:pk>/mark-present/<uuid:token>/\",\n                    MarkPresentView.as_view(),\n                    name=\"mark-present\",\n                ),\n                path(\n                    \"<int:pk>/registration/\",\n                    RegistrationView.as_view(),\n                    name=\"registration\",\n                ),\n                path(\"\", EventIndex.as_view(), name=\"index\"),\n                path(\"ical/nl.ics\", EventFeed(), name=\"ical-nl\"),\n                path(\"ical/en.ics\", EventFeed(), name=\"ical-en\"),\n            ]\n        ),\n    ),\n    path(\"association/alumni/\", AlumniEventsView.as_view(), name=\"alumni\"),\n]\n", "path": "website/events/urls.py"}], "after_files": [{"content": "\"\"\"Views provided by the events package.\"\"\"\n\nfrom django.contrib import messages\nfrom django.contrib.auth.decorators import login_required\nfrom django.http import Http404\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils import timezone\nfrom django.utils.decorators import method_decorator\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views import View\nfrom django.views.generic import DetailView, FormView, TemplateView\n\nfrom events import services\nfrom events.exceptions import RegistrationError\nfrom events.models import categories\nfrom events.services import is_user_registered\nfrom payments.models import Payment\n\nfrom .forms import FieldsForm\nfrom .models import Event, EventRegistration\n\n\nclass EventIndex(TemplateView):\n    \"\"\"Render the events calendar overview.\"\"\"\n\n    template_name = \"events/index.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        upcoming_activity = (\n            Event.objects.filter(published=True, end__gte=timezone.now())\n            .order_by(\"end\")\n            .first()\n        )\n        context[\"upcoming_activity\"] = upcoming_activity\n\n        return context\n\n\nclass EventDetail(DetailView):\n    \"\"\"Render a single event detail page.\"\"\"\n\n    model = Event\n    queryset = Event.objects.filter(published=True)\n    template_name = \"events/event.html\"\n    context_object_name = \"event\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"user\"] = self.request.user\n        context[\"payment_method_tpay\"] = Payment.TPAY\n\n        event = context[\"event\"]\n        if event.max_participants:\n            perc = 100.0 * len(event.participants) / event.max_participants\n            context[\"registration_percentage\"] = perc\n\n        try:\n            context[\"registration\"] = EventRegistration.objects.get(\n                event=event, member=self.request.member\n            )\n        except (EventRegistration.DoesNotExist, TypeError):\n            pass\n\n        registration_status = services.registration_status(\n            event, context.get(\"registration\"), self.request.member\n        )\n        context[\"registration_status\"] = services.registration_status_string(\n            registration_status, event, context.get(\"registration\")\n        )\n\n        context[\"show_cancel_status\"] = services.show_cancel_status(registration_status)\n        if context[\"show_cancel_status\"]:\n            cancel_status = services.cancel_status(event, context.get(\"registration\"))\n            context[\"cancel_info\"] = services.cancel_info_string(\n                event, cancel_status, registration_status\n            )\n\n        context[\"permissions\"] = services.event_permissions(self.request.member, event)\n\n        context[\"date_now\"] = timezone.now()\n\n        context[\"slide_size\"] = \"slide\"\n\n        context[\"participants\"] = event.participants.select_related(\n            \"member\", \"member__profile\"\n        )\n\n        return context\n\n\nclass AlumniEventsView(TemplateView):\n    \"\"\"Render the alumni events page.\"\"\"\n\n    template_name = \"events/alumni.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        events = Event.objects.filter(\n            published=True, category=categories.CATEGORY_ALUMNI, end__gte=timezone.now()\n        ).order_by(\"end\")[:3]\n        context[\"events\"] = events\n\n        return context\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass EventRegisterView(View):\n    \"\"\"Define a view that allows the user to register for an event using a POST request.\n\n    The user should be authenticated.\n    \"\"\"\n\n    def get(self, request, *args, **kwargs):\n        return redirect(\"events:event\", pk=kwargs[\"pk\"])\n\n    def post(self, request, *args, **kwargs):\n        event = get_object_or_404(Event, pk=kwargs[\"pk\"])\n        try:\n            services.create_registration(request.member, event)\n\n            if event.has_fields:\n                return redirect(\"events:registration\", event.pk)\n\n            messages.success(request, _(\"Registration successful.\"))\n        except RegistrationError as e:\n            messages.error(request, e)\n\n        return redirect(event)\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass EventCancelView(View):\n    \"\"\"Define a view that allows the user to cancel their event registration using a POST request.\n\n    The user should be authenticated.\n    \"\"\"\n\n    def get(self, request, *args, **kwargs):\n        return redirect(\"events:event\", pk=kwargs[\"pk\"])\n\n    def post(self, request, *args, **kwargs):\n        event = get_object_or_404(Event, pk=kwargs[\"pk\"])\n        try:\n            services.cancel_registration(request.member, event)\n            messages.success(request, _(\"Registration successfully cancelled.\"))\n        except RegistrationError as e:\n            messages.error(request, e)\n\n        return redirect(event)\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass RegistrationView(FormView):\n    \"\"\"Render a form that allows the user to change the details of their registration.\n\n    The user should be authenticated.\n    \"\"\"\n\n    form_class = FieldsForm\n    template_name = \"events/registration.html\"\n    event = None\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"event\"] = self.event\n        return context\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"fields\"] = services.registration_fields(\n            self.request, self.request.member, self.event\n        )\n        return kwargs\n\n    def form_valid(self, form):\n        values = form.field_values()\n        try:\n            services.update_registration(\n                self.request.member, self.event, field_values=values\n            )\n            messages.success(self.request, _(\"Registration successfully saved.\"))\n            return redirect(self.event)\n        except RegistrationError as e:\n            messages.error(self.request, e)\n            return self.render_to_response(self.get_context_data(form=form))\n\n    def dispatch(self, request, *args, **kwargs):\n        self.event = get_object_or_404(Event, pk=self.kwargs[\"pk\"])\n        try:\n            if self.event.has_fields:\n                return super().dispatch(request, *args, **kwargs)\n        except RegistrationError:\n            pass\n        return redirect(self.event)\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass MarkPresentView(View):\n    \"\"\"A view that allows uses to mark their presence at an event using a secret token.\"\"\"\n\n    def get(self, request, *args, **kwargs):\n        \"\"\"Mark a user as present.\n\n        Checks if the url is correct, the event has not ended yet, and the user is registered.\n        \"\"\"\n        event = get_object_or_404(Event, pk=kwargs[\"pk\"])\n        if kwargs[\"token\"] != event.mark_present_url_token:\n            messages.error(request, _(\"Invalid url.\"))\n        elif not request.member or not is_user_registered(request.member, event):\n            messages.error(request, _(\"You are not registered for this event.\"))\n        else:\n            registration = event.registrations.get(\n                member=request.member, date_cancelled=None\n            )\n\n            if registration.present:\n                messages.info(request, _(\"You were already marked as present.\"))\n            elif event.end < timezone.now():\n                messages.error(request, _(\"This event has already ended.\"))\n            else:\n                registration.present = True\n                registration.save()\n                messages.success(request, _(\"You have been marked as present.\"))\n\n        return redirect(event)\n\n\nclass NextEventView(View):\n    def get(self, request, *args, **kwargs):\n        \"\"\"HTTP redirect to the next event.\n\n        Checks if there is an upcoming event. Raise a 404 if none exists.\n        \"\"\"\n        upcoming_activity = (\n            Event.objects.filter(published=True, end__gte=timezone.now())\n            .order_by(\"end\")\n            .first()\n        )\n        if not upcoming_activity:\n            raise Http404(\"There is no upcoming event.\")\n\n        return redirect(upcoming_activity)\n", "path": "website/events/views.py"}, {"content": "\"\"\"Routes defined by the events package.\"\"\"\nfrom django.urls import include, path\n\nfrom events.feeds import EventFeed\nfrom events.views import (\n    AlumniEventsView,\n    EventCancelView,\n    EventDetail,\n    EventIndex,\n    EventRegisterView,\n    MarkPresentView,\n    NextEventView,\n    RegistrationView,\n)\n\napp_name = \"events\"\n\nurlpatterns = [\n    path(\n        \"events/\",\n        include(\n            [\n                path(\"<int:pk>/\", EventDetail.as_view(), name=\"event\"),\n                path(\"next/\", NextEventView.as_view(), name=\"next\"),\n                path(\"<slug:slug>/\", EventDetail.as_view(), name=\"event\"),\n                path(\n                    \"<int:pk>/registration/register/\",\n                    EventRegisterView.as_view(),\n                    name=\"register\",\n                ),\n                path(\n                    \"<int:pk>/registration/cancel/\",\n                    EventCancelView.as_view(),\n                    name=\"cancel\",\n                ),\n                path(\n                    \"<int:pk>/mark-present/<uuid:token>/\",\n                    MarkPresentView.as_view(),\n                    name=\"mark-present\",\n                ),\n                path(\n                    \"<int:pk>/registration/\",\n                    RegistrationView.as_view(),\n                    name=\"registration\",\n                ),\n                path(\"\", EventIndex.as_view(), name=\"index\"),\n                path(\"ical/nl.ics\", EventFeed(), name=\"ical-nl\"),\n                path(\"ical/en.ics\", EventFeed(), name=\"ical-en\"),\n            ]\n        ),\n    ),\n    path(\"association/alumni/\", AlumniEventsView.as_view(), name=\"alumni\"),\n]\n", "path": "website/events/urls.py"}]}