We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Edit information field in admin gives error page
### Describe the bug
The site gives the 500 error page when you try to edit information fields of registered users

### How to reproduce
Go to an event on the admin and press change on a user's registration. At "Fields:" press the "Edit Information Fields" button and the bug happens (found at parents day, Tim Kersten)

### Expected behaviour
I'd expect the appropriate page for editing a user's information fields.


--- 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/admin/views.py`
Content:
```
1 import csv
2 
3 from django.conf import settings
4 from django.contrib import messages
5 from django.contrib.admin import helpers
6 from django.contrib.admin.views.decorators import staff_member_required
7 from django.contrib.auth.mixins import PermissionRequiredMixin
8 from django.http import HttpResponse
9 from django.shortcuts import get_object_or_404, redirect
10 from django.utils import timezone
11 from django.utils.decorators import method_decorator
12 from django.utils.text import slugify
13 from django.utils.translation import gettext_lazy as _
14 from django.utils.translation import pgettext_lazy
15 from django.views import View
16 from django.views.generic import DetailView, FormView
17 
18 import qrcode
19 
20 from events import services
21 from events.decorators import organiser_only
22 from events.exceptions import RegistrationError
23 from events.forms import EventMessageForm, FieldsForm
24 from events.models import Event, EventRegistration
25 from payments.models import Payment
26 from pushnotifications.models import Category, Message
27 
28 
29 @method_decorator(staff_member_required, name="dispatch")
30 @method_decorator(organiser_only, name="dispatch")
31 class EventAdminDetails(DetailView, PermissionRequiredMixin):
32     """Render an overview of registrations for the specified event."""
33 
34     template_name = "events/admin/details.html"
35     model = Event
36     context_object_name = "event"
37     permission_required = "events.change_event"
38 
39     def get_context_data(self, **kwargs):
40         context = super().get_context_data(**kwargs)
41 
42         context.update({"payment": Payment, "has_permission": True, "site_url": "/"})
43 
44         return context
45 
46 
47 @method_decorator(staff_member_required, name="dispatch")
48 @method_decorator(organiser_only, name="dispatch")
49 class RegistrationAdminFields(FormView):
50     """Render a form that allows the user to change the details of their registration.
51 
52     The user should be authenticated.
53     """
54 
55     form_class = FieldsForm
56     template_name = "admin/change_form.html"
57     registration = None
58     admin = None
59 
60     def get_context_data(self, **kwargs):
61         context = super().get_context_data(**kwargs)
62         context.update(
63             {
64                 **self.admin.admin_site.each_context(self.request),
65                 "add": False,
66                 "change": True,
67                 "has_view_permission": True,
68                 "has_add_permission": False,
69                 "has_change_permission": self.request.user.has_perms(
70                     "events.change_eventregistration"
71                 ),
72                 "has_delete_permission": False,
73                 "has_editable_inline_admin_formsets": False,
74                 "app_label": "events",
75                 "opts": self.registration._meta,
76                 "is_popup": False,
77                 "save_as": False,
78                 "save_on_top": False,
79                 "original": self.registration,
80                 "obj_id": self.registration.pk,
81                 "title": _("Change registration fields"),
82                 "adminform": helpers.AdminForm(
83                     context["form"],
84                     ((None, {"fields": context["form"].fields.keys()}),),
85                     {},
86                 ),
87             }
88         )
89         return context
90 
91     def get_form_kwargs(self):
92         kwargs = super().get_form_kwargs()
93         kwargs["fields"] = services.registration_fields(
94             self.request, registration=self.registration
95         )
96         return kwargs
97 
98     def form_valid(self, form):
99         values = form.field_values()
100         try:
101             services.update_registration(
102                 registration=self.registration,
103                 field_values=values,
104                 actor=self.request.user,
105             )
106             messages.success(self.request, _("Registration successfully saved."))
107             if "_save" in self.request.POST:
108                 return redirect(
109                     "admin:events_eventregistration_change", self.registration.pk
110                 )
111         except RegistrationError as e:
112             messages.error(self.request, e)
113         return self.render_to_response(self.get_context_data(form=form))
114 
115     def dispatch(self, request, *args, **kwargs):
116         self.registration = get_object_or_404(
117             EventRegistration, pk=self.kwargs["registration"]
118         )
119         try:
120             if self.registration.event.has_fields:
121                 return super().dispatch(request, *args, **kwargs)
122         except RegistrationError:
123             pass
124         return redirect("admin:events_eventregistration_change", self.registration.pk)
125 
126 
127 @method_decorator(staff_member_required, name="dispatch")
128 @method_decorator(organiser_only, name="dispatch")
129 class EventMessage(FormView):
130     """Renders a form that allows the user to create a push notification for all users registers to the event."""
131 
132     form_class = EventMessageForm
133     template_name = "events/admin/message_form.html"
134     admin = None
135     event = None
136 
137     def get_context_data(self, **kwargs):
138         context = super().get_context_data(**kwargs)
139         context.update(
140             {
141                 **self.admin.admin_site.each_context(self.request),
142                 "add": False,
143                 "change": True,
144                 "has_view_permission": True,
145                 "has_add_permission": False,
146                 "has_change_permission": self.request.user.has_perms(
147                     "events.change_event"
148                 ),
149                 "has_delete_permission": False,
150                 "has_editable_inline_admin_formsets": False,
151                 "app_label": "events",
152                 "opts": self.event._meta,
153                 "is_popup": False,
154                 "save_as": False,
155                 "save_on_top": False,
156                 "original": self.event,
157                 "obj_id": self.event.pk,
158                 "title": _("Send push notification"),
159                 "adminform": helpers.AdminForm(
160                     context["form"],
161                     ((None, {"fields": context["form"].fields.keys()}),),
162                     {},
163                 ),
164             }
165         )
166         return context
167 
168     def form_valid(self, form):
169         values = form.cleaned_data
170         if not values["url"]:
171             values["url"] = settings.BASE_URL + self.event.get_absolute_url()
172         message = Message(
173             title=values["title"],
174             body=values["body"],
175             url=values["url"],
176             category=Category.objects.get(key=Category.EVENT),
177         )
178         message.save()
179         message.users.set([r.member for r in self.event.participants if r.member])
180         message.send()
181 
182         messages.success(self.request, _("Message sent successfully."))
183         if "_save" in self.request.POST:
184             return redirect("admin:events_event_details", self.event.pk)
185         return super().form_valid(form)
186 
187     def dispatch(self, request, *args, **kwargs):
188         self.event = get_object_or_404(Event, pk=self.kwargs["pk"])
189         return super().dispatch(request, *args, **kwargs)
190 
191 
192 @method_decorator(staff_member_required, name="dispatch")
193 @method_decorator(organiser_only, name="dispatch")
194 class EventRegistrationsExport(View, PermissionRequiredMixin):
195     """View to export registrations."""
196 
197     template_name = "events/admin/details.html"
198     permission_required = "events.change_event"
199 
200     def get(self, request, pk):
201         """Export the registration of a specified event.
202 
203         :param request: the request object
204         :param pk: the primary key of the event
205         :return: A CSV containing all registrations for the event
206         """
207         event = get_object_or_404(Event, pk=pk)
208         extra_fields = event.registrationinformationfield_set.all()
209         registrations = event.eventregistration_set.all()
210 
211         header_fields = (
212             [
213                 _("Name"),
214                 _("Email"),
215                 _("Paid"),
216                 _("Present"),
217                 _("Status"),
218                 _("Phone number"),
219             ]
220             + [field.name for field in extra_fields]
221             + [_("Date"), _("Date cancelled")]
222         )
223 
224         rows = []
225         if event.price == 0:
226             header_fields.remove(_("Paid"))
227         for registration in registrations:
228             if registration.member:
229                 name = registration.member.get_full_name()
230             else:
231                 name = registration.name
232             status = pgettext_lazy("registration status", "registered").capitalize()
233             cancelled = None
234             if registration.date_cancelled:
235                 if registration.is_late_cancellation():
236                     status = pgettext_lazy(
237                         "registration status", "late cancellation"
238                     ).capitalize()
239                 else:
240                     status = pgettext_lazy(
241                         "registration status", "cancelled"
242                     ).capitalize()
243                 cancelled = timezone.localtime(registration.date_cancelled)
244 
245             elif registration.queue_position:
246                 status = pgettext_lazy("registration status", "waiting")
247             data = {
248                 _("Name"): name,
249                 _("Date"): timezone.localtime(registration.date),
250                 _("Present"): _("Yes") if registration.present else "",
251                 _("Phone number"): (
252                     registration.phone_number if registration.phone_number else ""
253                 ),
254                 _("Email"): (registration.email if registration.email else ""),
255                 _("Status"): status,
256                 _("Date cancelled"): cancelled,
257             }
258             if event.price > 0:
259                 if registration.is_paid():
260                     data[_("Paid")] = registration.payment.get_type_display()
261                 else:
262                     data[_("Paid")] = _("No")
263 
264             data.update(
265                 {
266                     field["field"].name: field["value"]
267                     for field in registration.information_fields
268                 }
269             )
270             rows.append(data)
271 
272         response = HttpResponse(content_type="text/csv")
273         writer = csv.DictWriter(response, header_fields)
274         writer.writeheader()
275 
276         rows = sorted(
277             rows,
278             key=lambda row: (
279                 row[_("Status")]
280                 == pgettext_lazy(
281                     "registration status", "late cancellation"
282                 ).capitalize(),
283                 row[_("Date")],
284             ),
285             reverse=True,
286         )
287 
288         for row in rows:
289             writer.writerow(row)
290 
291         response[
292             "Content-Disposition"
293         ] = f'attachment; filename="{slugify(event.title)}.csv"'
294         return response
295 
296 
297 @method_decorator(staff_member_required, name="dispatch")
298 @method_decorator(organiser_only, name="dispatch")
299 class EventMarkPresentQR(View):
300     def get(self, request, *args, **kwargs):
301         event = get_object_or_404(Event, pk=kwargs["pk"])
302         image = qrcode.make(event.mark_present_url)
303 
304         response = HttpResponse(content_type="image/png")
305         image.save(response, "PNG")
306 
307         return response
308
```
--- 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/admin/views.py b/website/events/admin/views.py
--- a/website/events/admin/views.py
+++ b/website/events/admin/views.py
@@ -66,7 +66,7 @@
                 "change": True,
                 "has_view_permission": True,
                 "has_add_permission": False,
-                "has_change_permission": self.request.user.has_perms(
+                "has_change_permission": self.request.user.has_perm(
                     "events.change_eventregistration"
                 ),
                 "has_delete_permission": False,
@@ -143,7 +143,7 @@
                 "change": True,
                 "has_view_permission": True,
                 "has_add_permission": False,
-                "has_change_permission": self.request.user.has_perms(
+                "has_change_permission": self.request.user.has_perm(
                     "events.change_event"
                 ),
                 "has_delete_permission": False,

{"golden_diff": "diff --git a/website/events/admin/views.py b/website/events/admin/views.py\n--- a/website/events/admin/views.py\n+++ b/website/events/admin/views.py\n@@ -66,7 +66,7 @@\n                 \"change\": True,\n                 \"has_view_permission\": True,\n                 \"has_add_permission\": False,\n-                \"has_change_permission\": self.request.user.has_perms(\n+                \"has_change_permission\": self.request.user.has_perm(\n                     \"events.change_eventregistration\"\n                 ),\n                 \"has_delete_permission\": False,\n@@ -143,7 +143,7 @@\n                 \"change\": True,\n                 \"has_view_permission\": True,\n                 \"has_add_permission\": False,\n-                \"has_change_permission\": self.request.user.has_perms(\n+                \"has_change_permission\": self.request.user.has_perm(\n                     \"events.change_event\"\n                 ),\n                 \"has_delete_permission\": False,\n", "issue": "Edit information field in admin gives error page\n### Describe the bug\r\nThe site gives the 500 error page when you try to edit information fields of registered users\r\n\r\n### How to reproduce\r\nGo to an event on the admin and press change on a user's registration. At \"Fields:\" press the \"Edit Information Fields\" button and the bug happens (found at parents day, Tim Kersten)\r\n\r\n### Expected behaviour\r\nI'd expect the appropriate page for editing a user's information fields.\r\n\n", "before_files": [{"content": "import csv\n\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.contrib.admin import helpers\nfrom django.contrib.admin.views.decorators import staff_member_required\nfrom django.contrib.auth.mixins import PermissionRequiredMixin\nfrom django.http import HttpResponse\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils import timezone\nfrom django.utils.decorators import method_decorator\nfrom django.utils.text import slugify\nfrom django.utils.translation import gettext_lazy as _\nfrom django.utils.translation import pgettext_lazy\nfrom django.views import View\nfrom django.views.generic import DetailView, FormView\n\nimport qrcode\n\nfrom events import services\nfrom events.decorators import organiser_only\nfrom events.exceptions import RegistrationError\nfrom events.forms import EventMessageForm, FieldsForm\nfrom events.models import Event, EventRegistration\nfrom payments.models import Payment\nfrom pushnotifications.models import Category, Message\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass EventAdminDetails(DetailView, PermissionRequiredMixin):\n    \"\"\"Render an overview of registrations for the specified event.\"\"\"\n\n    template_name = \"events/admin/details.html\"\n    model = Event\n    context_object_name = \"event\"\n    permission_required = \"events.change_event\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        context.update({\"payment\": Payment, \"has_permission\": True, \"site_url\": \"/\"})\n\n        return context\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass RegistrationAdminFields(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 = \"admin/change_form.html\"\n    registration = None\n    admin = None\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context.update(\n            {\n                **self.admin.admin_site.each_context(self.request),\n                \"add\": False,\n                \"change\": True,\n                \"has_view_permission\": True,\n                \"has_add_permission\": False,\n                \"has_change_permission\": self.request.user.has_perms(\n                    \"events.change_eventregistration\"\n                ),\n                \"has_delete_permission\": False,\n                \"has_editable_inline_admin_formsets\": False,\n                \"app_label\": \"events\",\n                \"opts\": self.registration._meta,\n                \"is_popup\": False,\n                \"save_as\": False,\n                \"save_on_top\": False,\n                \"original\": self.registration,\n                \"obj_id\": self.registration.pk,\n                \"title\": _(\"Change registration fields\"),\n                \"adminform\": helpers.AdminForm(\n                    context[\"form\"],\n                    ((None, {\"fields\": context[\"form\"].fields.keys()}),),\n                    {},\n                ),\n            }\n        )\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, registration=self.registration\n        )\n        return kwargs\n\n    def form_valid(self, form):\n        values = form.field_values()\n        try:\n            services.update_registration(\n                registration=self.registration,\n                field_values=values,\n                actor=self.request.user,\n            )\n            messages.success(self.request, _(\"Registration successfully saved.\"))\n            if \"_save\" in self.request.POST:\n                return redirect(\n                    \"admin:events_eventregistration_change\", self.registration.pk\n                )\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.registration = get_object_or_404(\n            EventRegistration, pk=self.kwargs[\"registration\"]\n        )\n        try:\n            if self.registration.event.has_fields:\n                return super().dispatch(request, *args, **kwargs)\n        except RegistrationError:\n            pass\n        return redirect(\"admin:events_eventregistration_change\", self.registration.pk)\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass EventMessage(FormView):\n    \"\"\"Renders a form that allows the user to create a push notification for all users registers to the event.\"\"\"\n\n    form_class = EventMessageForm\n    template_name = \"events/admin/message_form.html\"\n    admin = None\n    event = None\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context.update(\n            {\n                **self.admin.admin_site.each_context(self.request),\n                \"add\": False,\n                \"change\": True,\n                \"has_view_permission\": True,\n                \"has_add_permission\": False,\n                \"has_change_permission\": self.request.user.has_perms(\n                    \"events.change_event\"\n                ),\n                \"has_delete_permission\": False,\n                \"has_editable_inline_admin_formsets\": False,\n                \"app_label\": \"events\",\n                \"opts\": self.event._meta,\n                \"is_popup\": False,\n                \"save_as\": False,\n                \"save_on_top\": False,\n                \"original\": self.event,\n                \"obj_id\": self.event.pk,\n                \"title\": _(\"Send push notification\"),\n                \"adminform\": helpers.AdminForm(\n                    context[\"form\"],\n                    ((None, {\"fields\": context[\"form\"].fields.keys()}),),\n                    {},\n                ),\n            }\n        )\n        return context\n\n    def form_valid(self, form):\n        values = form.cleaned_data\n        if not values[\"url\"]:\n            values[\"url\"] = settings.BASE_URL + self.event.get_absolute_url()\n        message = Message(\n            title=values[\"title\"],\n            body=values[\"body\"],\n            url=values[\"url\"],\n            category=Category.objects.get(key=Category.EVENT),\n        )\n        message.save()\n        message.users.set([r.member for r in self.event.participants if r.member])\n        message.send()\n\n        messages.success(self.request, _(\"Message sent successfully.\"))\n        if \"_save\" in self.request.POST:\n            return redirect(\"admin:events_event_details\", self.event.pk)\n        return super().form_valid(form)\n\n    def dispatch(self, request, *args, **kwargs):\n        self.event = get_object_or_404(Event, pk=self.kwargs[\"pk\"])\n        return super().dispatch(request, *args, **kwargs)\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass EventRegistrationsExport(View, PermissionRequiredMixin):\n    \"\"\"View to export registrations.\"\"\"\n\n    template_name = \"events/admin/details.html\"\n    permission_required = \"events.change_event\"\n\n    def get(self, request, pk):\n        \"\"\"Export the registration of a specified event.\n\n        :param request: the request object\n        :param pk: the primary key of the event\n        :return: A CSV containing all registrations for the event\n        \"\"\"\n        event = get_object_or_404(Event, pk=pk)\n        extra_fields = event.registrationinformationfield_set.all()\n        registrations = event.eventregistration_set.all()\n\n        header_fields = (\n            [\n                _(\"Name\"),\n                _(\"Email\"),\n                _(\"Paid\"),\n                _(\"Present\"),\n                _(\"Status\"),\n                _(\"Phone number\"),\n            ]\n            + [field.name for field in extra_fields]\n            + [_(\"Date\"), _(\"Date cancelled\")]\n        )\n\n        rows = []\n        if event.price == 0:\n            header_fields.remove(_(\"Paid\"))\n        for registration in registrations:\n            if registration.member:\n                name = registration.member.get_full_name()\n            else:\n                name = registration.name\n            status = pgettext_lazy(\"registration status\", \"registered\").capitalize()\n            cancelled = None\n            if registration.date_cancelled:\n                if registration.is_late_cancellation():\n                    status = pgettext_lazy(\n                        \"registration status\", \"late cancellation\"\n                    ).capitalize()\n                else:\n                    status = pgettext_lazy(\n                        \"registration status\", \"cancelled\"\n                    ).capitalize()\n                cancelled = timezone.localtime(registration.date_cancelled)\n\n            elif registration.queue_position:\n                status = pgettext_lazy(\"registration status\", \"waiting\")\n            data = {\n                _(\"Name\"): name,\n                _(\"Date\"): timezone.localtime(registration.date),\n                _(\"Present\"): _(\"Yes\") if registration.present else \"\",\n                _(\"Phone number\"): (\n                    registration.phone_number if registration.phone_number else \"\"\n                ),\n                _(\"Email\"): (registration.email if registration.email else \"\"),\n                _(\"Status\"): status,\n                _(\"Date cancelled\"): cancelled,\n            }\n            if event.price > 0:\n                if registration.is_paid():\n                    data[_(\"Paid\")] = registration.payment.get_type_display()\n                else:\n                    data[_(\"Paid\")] = _(\"No\")\n\n            data.update(\n                {\n                    field[\"field\"].name: field[\"value\"]\n                    for field in registration.information_fields\n                }\n            )\n            rows.append(data)\n\n        response = HttpResponse(content_type=\"text/csv\")\n        writer = csv.DictWriter(response, header_fields)\n        writer.writeheader()\n\n        rows = sorted(\n            rows,\n            key=lambda row: (\n                row[_(\"Status\")]\n                == pgettext_lazy(\n                    \"registration status\", \"late cancellation\"\n                ).capitalize(),\n                row[_(\"Date\")],\n            ),\n            reverse=True,\n        )\n\n        for row in rows:\n            writer.writerow(row)\n\n        response[\n            \"Content-Disposition\"\n        ] = f'attachment; filename=\"{slugify(event.title)}.csv\"'\n        return response\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass EventMarkPresentQR(View):\n    def get(self, request, *args, **kwargs):\n        event = get_object_or_404(Event, pk=kwargs[\"pk\"])\n        image = qrcode.make(event.mark_present_url)\n\n        response = HttpResponse(content_type=\"image/png\")\n        image.save(response, \"PNG\")\n\n        return response\n", "path": "website/events/admin/views.py"}], "after_files": [{"content": "import csv\n\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.contrib.admin import helpers\nfrom django.contrib.admin.views.decorators import staff_member_required\nfrom django.contrib.auth.mixins import PermissionRequiredMixin\nfrom django.http import HttpResponse\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils import timezone\nfrom django.utils.decorators import method_decorator\nfrom django.utils.text import slugify\nfrom django.utils.translation import gettext_lazy as _\nfrom django.utils.translation import pgettext_lazy\nfrom django.views import View\nfrom django.views.generic import DetailView, FormView\n\nimport qrcode\n\nfrom events import services\nfrom events.decorators import organiser_only\nfrom events.exceptions import RegistrationError\nfrom events.forms import EventMessageForm, FieldsForm\nfrom events.models import Event, EventRegistration\nfrom payments.models import Payment\nfrom pushnotifications.models import Category, Message\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass EventAdminDetails(DetailView, PermissionRequiredMixin):\n    \"\"\"Render an overview of registrations for the specified event.\"\"\"\n\n    template_name = \"events/admin/details.html\"\n    model = Event\n    context_object_name = \"event\"\n    permission_required = \"events.change_event\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        context.update({\"payment\": Payment, \"has_permission\": True, \"site_url\": \"/\"})\n\n        return context\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass RegistrationAdminFields(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 = \"admin/change_form.html\"\n    registration = None\n    admin = None\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context.update(\n            {\n                **self.admin.admin_site.each_context(self.request),\n                \"add\": False,\n                \"change\": True,\n                \"has_view_permission\": True,\n                \"has_add_permission\": False,\n                \"has_change_permission\": self.request.user.has_perm(\n                    \"events.change_eventregistration\"\n                ),\n                \"has_delete_permission\": False,\n                \"has_editable_inline_admin_formsets\": False,\n                \"app_label\": \"events\",\n                \"opts\": self.registration._meta,\n                \"is_popup\": False,\n                \"save_as\": False,\n                \"save_on_top\": False,\n                \"original\": self.registration,\n                \"obj_id\": self.registration.pk,\n                \"title\": _(\"Change registration fields\"),\n                \"adminform\": helpers.AdminForm(\n                    context[\"form\"],\n                    ((None, {\"fields\": context[\"form\"].fields.keys()}),),\n                    {},\n                ),\n            }\n        )\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, registration=self.registration\n        )\n        return kwargs\n\n    def form_valid(self, form):\n        values = form.field_values()\n        try:\n            services.update_registration(\n                registration=self.registration,\n                field_values=values,\n                actor=self.request.user,\n            )\n            messages.success(self.request, _(\"Registration successfully saved.\"))\n            if \"_save\" in self.request.POST:\n                return redirect(\n                    \"admin:events_eventregistration_change\", self.registration.pk\n                )\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.registration = get_object_or_404(\n            EventRegistration, pk=self.kwargs[\"registration\"]\n        )\n        try:\n            if self.registration.event.has_fields:\n                return super().dispatch(request, *args, **kwargs)\n        except RegistrationError:\n            pass\n        return redirect(\"admin:events_eventregistration_change\", self.registration.pk)\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass EventMessage(FormView):\n    \"\"\"Renders a form that allows the user to create a push notification for all users registers to the event.\"\"\"\n\n    form_class = EventMessageForm\n    template_name = \"events/admin/message_form.html\"\n    admin = None\n    event = None\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context.update(\n            {\n                **self.admin.admin_site.each_context(self.request),\n                \"add\": False,\n                \"change\": True,\n                \"has_view_permission\": True,\n                \"has_add_permission\": False,\n                \"has_change_permission\": self.request.user.has_perm(\n                    \"events.change_event\"\n                ),\n                \"has_delete_permission\": False,\n                \"has_editable_inline_admin_formsets\": False,\n                \"app_label\": \"events\",\n                \"opts\": self.event._meta,\n                \"is_popup\": False,\n                \"save_as\": False,\n                \"save_on_top\": False,\n                \"original\": self.event,\n                \"obj_id\": self.event.pk,\n                \"title\": _(\"Send push notification\"),\n                \"adminform\": helpers.AdminForm(\n                    context[\"form\"],\n                    ((None, {\"fields\": context[\"form\"].fields.keys()}),),\n                    {},\n                ),\n            }\n        )\n        return context\n\n    def form_valid(self, form):\n        values = form.cleaned_data\n        if not values[\"url\"]:\n            values[\"url\"] = settings.BASE_URL + self.event.get_absolute_url()\n        message = Message(\n            title=values[\"title\"],\n            body=values[\"body\"],\n            url=values[\"url\"],\n            category=Category.objects.get(key=Category.EVENT),\n        )\n        message.save()\n        message.users.set([r.member for r in self.event.participants if r.member])\n        message.send()\n\n        messages.success(self.request, _(\"Message sent successfully.\"))\n        if \"_save\" in self.request.POST:\n            return redirect(\"admin:events_event_details\", self.event.pk)\n        return super().form_valid(form)\n\n    def dispatch(self, request, *args, **kwargs):\n        self.event = get_object_or_404(Event, pk=self.kwargs[\"pk\"])\n        return super().dispatch(request, *args, **kwargs)\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass EventRegistrationsExport(View, PermissionRequiredMixin):\n    \"\"\"View to export registrations.\"\"\"\n\n    template_name = \"events/admin/details.html\"\n    permission_required = \"events.change_event\"\n\n    def get(self, request, pk):\n        \"\"\"Export the registration of a specified event.\n\n        :param request: the request object\n        :param pk: the primary key of the event\n        :return: A CSV containing all registrations for the event\n        \"\"\"\n        event = get_object_or_404(Event, pk=pk)\n        extra_fields = event.registrationinformationfield_set.all()\n        registrations = event.eventregistration_set.all()\n\n        header_fields = (\n            [\n                _(\"Name\"),\n                _(\"Email\"),\n                _(\"Paid\"),\n                _(\"Present\"),\n                _(\"Status\"),\n                _(\"Phone number\"),\n            ]\n            + [field.name for field in extra_fields]\n            + [_(\"Date\"), _(\"Date cancelled\")]\n        )\n\n        rows = []\n        if event.price == 0:\n            header_fields.remove(_(\"Paid\"))\n        for registration in registrations:\n            if registration.member:\n                name = registration.member.get_full_name()\n            else:\n                name = registration.name\n            status = pgettext_lazy(\"registration status\", \"registered\").capitalize()\n            cancelled = None\n            if registration.date_cancelled:\n                if registration.is_late_cancellation():\n                    status = pgettext_lazy(\n                        \"registration status\", \"late cancellation\"\n                    ).capitalize()\n                else:\n                    status = pgettext_lazy(\n                        \"registration status\", \"cancelled\"\n                    ).capitalize()\n                cancelled = timezone.localtime(registration.date_cancelled)\n\n            elif registration.queue_position:\n                status = pgettext_lazy(\"registration status\", \"waiting\")\n            data = {\n                _(\"Name\"): name,\n                _(\"Date\"): timezone.localtime(registration.date),\n                _(\"Present\"): _(\"Yes\") if registration.present else \"\",\n                _(\"Phone number\"): (\n                    registration.phone_number if registration.phone_number else \"\"\n                ),\n                _(\"Email\"): (registration.email if registration.email else \"\"),\n                _(\"Status\"): status,\n                _(\"Date cancelled\"): cancelled,\n            }\n            if event.price > 0:\n                if registration.is_paid():\n                    data[_(\"Paid\")] = registration.payment.get_type_display()\n                else:\n                    data[_(\"Paid\")] = _(\"No\")\n\n            data.update(\n                {\n                    field[\"field\"].name: field[\"value\"]\n                    for field in registration.information_fields\n                }\n            )\n            rows.append(data)\n\n        response = HttpResponse(content_type=\"text/csv\")\n        writer = csv.DictWriter(response, header_fields)\n        writer.writeheader()\n\n        rows = sorted(\n            rows,\n            key=lambda row: (\n                row[_(\"Status\")]\n                == pgettext_lazy(\n                    \"registration status\", \"late cancellation\"\n                ).capitalize(),\n                row[_(\"Date\")],\n            ),\n            reverse=True,\n        )\n\n        for row in rows:\n            writer.writerow(row)\n\n        response[\n            \"Content-Disposition\"\n        ] = f'attachment; filename=\"{slugify(event.title)}.csv\"'\n        return response\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(organiser_only, name=\"dispatch\")\nclass EventMarkPresentQR(View):\n    def get(self, request, *args, **kwargs):\n        event = get_object_or_404(Event, pk=kwargs[\"pk\"])\n        image = qrcode.make(event.mark_present_url)\n\n        response = HttpResponse(content_type=\"image/png\")\n        image.save(response, \"PNG\")\n\n        return response\n", "path": "website/events/admin/views.py"}]}