We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Can't set registration information fields from admin (for non-member registrations)
### Describe the bug
It is not possible to manually set the event registration information fields from the admin. This is quite problematic when adding non-member's registrations

### How to reproduce
Steps to reproduce the behaviour:
1. add a manual event registration
2. try to edit the information fields (this works)
3. you cannot save it

### Expected behaviour
It should save



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

{"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@@ -97,7 +97,9 @@\n         values = form.field_values()\n         try:\n             services.update_registration(\n-                registration=self.registration, field_values=values\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", "issue": "Can't set registration information fields from admin (for non-member registrations)\n### Describe the bug\r\nIt is not possible to manually set the event registration information fields from the admin. This is quite problematic when adding non-member's registrations\r\n\r\n### How to reproduce\r\nSteps to reproduce the behaviour:\r\n1. add a manual event registration\r\n2. try to edit the information fields (this works)\r\n3. you cannot save it\r\n\r\n### Expected behaviour\r\nIt should save\r\n\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 pgettext_lazy\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views import View\nfrom django.views.generic import DetailView, FormView\n\nfrom events import services\nfrom events.decorators import organiser_only\nfrom events.exceptions import RegistrationError\nfrom events.forms import FieldsForm, EventMessageForm\nfrom payments.models import Payment\nfrom pushnotifications.models import Message, Category\nfrom events.models import Event, EventRegistration\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, field_values=values\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\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", "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 pgettext_lazy\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views import View\nfrom django.views.generic import DetailView, FormView\n\nfrom events import services\nfrom events.decorators import organiser_only\nfrom events.exceptions import RegistrationError\nfrom events.forms import FieldsForm, EventMessageForm\nfrom payments.models import Payment\nfrom pushnotifications.models import Message, Category\nfrom events.models import Event, EventRegistration\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\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", "path": "website/events/admin/views.py"}]}