We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
AttributeError: 'Event' object has no attribute 'title_en'
Sentry Issue: [CONCREXIT-70](https://sentry.io/organizations/thalia/issues/2487433496/?referrer=github_integration)

```
AttributeError: 'Event' object has no attribute 'title_en'
(9 additional frame(s) were not displayed)
...
  File "django/contrib/admin/options.py", line 1540, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
  File "django/contrib/admin/options.py", line 1586, in _changeform_view
    self.save_model(request, new_object, form, not add)
  File "photos/admin.py", line 45, in save_model
    super().save_model(request, obj, form, change)
  File "django/contrib/admin/options.py", line 1099, in save_model
    obj.save()
  File "photos/models.py", line 158, in save
    self.title = self.event.title_en
```

--- 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/photos/models.py`
Content:
```
1 import hashlib
2 import logging
3 import os
4 import random
5 
6 from django.conf import settings
7 from django.core.exceptions import ValidationError
8 from django.db import models
9 from django.urls import reverse
10 from django.utils import timezone
11 from django.utils.functional import cached_property
12 from django.utils.translation import gettext_lazy as _
13 
14 from members.models import Member
15 from events.models import Event
16 from pushnotifications.models import ScheduledMessage, Category
17 
18 COVER_FILENAME = "cover.jpg"
19 
20 
21 logger = logging.getLogger(__name__)
22 
23 
24 def photo_uploadto(instance, filename):
25     """Get path of file to upload to."""
26     num = instance.album.photo_set.count()
27     extension = os.path.splitext(filename)[1]
28     new_filename = str(num).zfill(4) + extension
29     return os.path.join(Album.photosdir, instance.album.dirname, new_filename)
30 
31 
32 class Photo(models.Model):
33     """Model for a Photo object."""
34 
35     album = models.ForeignKey(
36         "Album", on_delete=models.CASCADE, verbose_name=_("album")
37     )
38 
39     file = models.ImageField(_("file"), upload_to=photo_uploadto)
40 
41     rotation = models.IntegerField(
42         verbose_name=_("rotation"),
43         default=0,
44         choices=((x, x) for x in (0, 90, 180, 270)),
45         help_text=_("This does not modify the original image file."),
46     )
47 
48     hidden = models.BooleanField(_("hidden"), default=False)
49 
50     _digest = models.CharField("digest", max_length=40,)
51 
52     def __init__(self, *args, **kwargs):
53         """Initialize Photo object and set the file if it exists."""
54         super().__init__(*args, **kwargs)
55         if self.file:
56             self.original_file = self.file.path
57         else:
58             self.original_file = ""
59 
60     def __str__(self):
61         """Return the filename of a Photo object."""
62         return os.path.basename(self.file.name)
63 
64     class Meta:
65         """Meta class for Photo."""
66 
67         ordering = ("file",)
68 
69 
70 class Album(models.Model):
71     """Model for Album objects."""
72 
73     title = models.CharField(
74         _("title"),
75         blank=True,
76         max_length=200,
77         help_text=_("Leave empty to take over the title of the event"),
78     )
79 
80     dirname = models.CharField(verbose_name=_("directory name"), max_length=200,)
81 
82     date = models.DateField(
83         verbose_name=_("date"),
84         blank=True,
85         help_text=_("Leave empty to take over the date of the event"),
86     )
87 
88     slug = models.SlugField(verbose_name=_("slug"), unique=True,)
89 
90     hidden = models.BooleanField(verbose_name=_("hidden"), default=False)
91 
92     new_album_notification = models.ForeignKey(
93         ScheduledMessage, on_delete=models.deletion.SET_NULL, blank=True, null=True
94     )
95 
96     event = models.ForeignKey(Event, on_delete=models.SET_NULL, blank=True, null=True)
97 
98     _cover = models.OneToOneField(
99         Photo,
100         on_delete=models.SET_NULL,
101         blank=True,
102         null=True,
103         related_name="covered_album",
104         verbose_name=_("cover image"),
105     )
106 
107     shareable = models.BooleanField(verbose_name=_("shareable"), default=False)
108 
109     photosdir = "photos"
110     photospath = os.path.join(settings.MEDIA_ROOT, photosdir)
111 
112     @cached_property
113     def cover(self):
114         """Return cover of Album.
115 
116         If a cover is not set, return a random photo or None if there are no photos.
117         """
118         cover = None
119         if self._cover is not None:
120             return self._cover
121         if self.photo_set.exists():
122             random.seed(self.dirname)
123             cover = random.choice(self.photo_set.all())
124         return cover
125 
126     def __str__(self):
127         """Get string representation of Album."""
128         return "{} {}".format(self.date.strftime("%Y-%m-%d"), self.title)
129 
130     def get_absolute_url(self):
131         """Get url of Album."""
132         return reverse("photos:album", args=[str(self.slug)])
133 
134     def clean(self):
135         super().clean()
136         errors = {}
137 
138         if not self.title and not self.event:
139             errors.update(
140                 {"title": _("This field is required if there is no event selected.")}
141             )
142 
143         if not self.date and not self.event:
144             errors.update(
145                 {"date": _("This field is required if there is no event selected.")}
146             )
147 
148         if errors:
149             raise ValidationError(errors)
150 
151     def save(self, **kwargs):
152         """Save album and send appropriate notifications."""
153         # dirname is only set for new objects, to avoid ever changing it
154         if self.pk is None:
155             self.dirname = self.slug
156 
157         if not self.title and self.event:
158             self.title = self.event.title_en
159 
160         if not self.date:
161             self.date = self.event.start.date()
162 
163         if not self.hidden and (
164             self.new_album_notification is None or not self.new_album_notification.sent
165         ):
166             new_album_notification_time = timezone.now() + timezone.timedelta(hours=1)
167             new_album_notification = ScheduledMessage()
168 
169             if (
170                 self.new_album_notification is not None
171                 and not self.new_album_notification.sent
172             ):
173                 new_album_notification = self.new_album_notification
174 
175             new_album_notification.title_en = "New album uploaded"
176             new_album_notification.body_en = (
177                 f"A new photo album '{self.title}' has just been uploaded"
178             )
179             new_album_notification.category = Category.objects.get(key=Category.PHOTO)
180             new_album_notification.url = f"{settings.BASE_URL}{self.get_absolute_url()}"
181             new_album_notification.time = new_album_notification_time
182             new_album_notification.save()
183             self.new_album_notification = new_album_notification
184             self.new_album_notification.users.set(Member.current_members.all())
185         elif (
186             self.hidden
187             and self.new_album_notification is not None
188             and not self.new_album_notification.sent
189         ):
190             existing_notification = self.new_album_notification
191             self.new_album_notification = None
192             existing_notification.delete()
193 
194         super().save(**kwargs)
195 
196     @property
197     def access_token(self):
198         """Return access token for album."""
199         return hashlib.sha256(
200             "{}album{}".format(settings.SECRET_KEY, self.pk).encode("utf-8")
201         ).hexdigest()
202 
203     class Meta:
204         """Meta class for Album."""
205 
206         ordering = ("-date", "title")
207
```
--- 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/photos/models.py b/website/photos/models.py
--- a/website/photos/models.py
+++ b/website/photos/models.py
@@ -155,7 +155,7 @@
             self.dirname = self.slug
 
         if not self.title and self.event:
-            self.title = self.event.title_en
+            self.title = self.event.title
 
         if not self.date:
             self.date = self.event.start.date()

{"golden_diff": "diff --git a/website/photos/models.py b/website/photos/models.py\n--- a/website/photos/models.py\n+++ b/website/photos/models.py\n@@ -155,7 +155,7 @@\n             self.dirname = self.slug\n \n         if not self.title and self.event:\n-            self.title = self.event.title_en\n+            self.title = self.event.title\n \n         if not self.date:\n             self.date = self.event.start.date()\n", "issue": "AttributeError: 'Event' object has no attribute 'title_en'\nSentry Issue: [CONCREXIT-70](https://sentry.io/organizations/thalia/issues/2487433496/?referrer=github_integration)\n\n```\nAttributeError: 'Event' object has no attribute 'title_en'\n(9 additional frame(s) were not displayed)\n...\n  File \"django/contrib/admin/options.py\", line 1540, in changeform_view\n    return self._changeform_view(request, object_id, form_url, extra_context)\n  File \"django/contrib/admin/options.py\", line 1586, in _changeform_view\n    self.save_model(request, new_object, form, not add)\n  File \"photos/admin.py\", line 45, in save_model\n    super().save_model(request, obj, form, change)\n  File \"django/contrib/admin/options.py\", line 1099, in save_model\n    obj.save()\n  File \"photos/models.py\", line 158, in save\n    self.title = self.event.title_en\n```\n", "before_files": [{"content": "import hashlib\nimport logging\nimport os\nimport random\n\nfrom django.conf import settings\nfrom django.core.exceptions import ValidationError\nfrom django.db import models\nfrom django.urls import reverse\nfrom django.utils import timezone\nfrom django.utils.functional import cached_property\nfrom django.utils.translation import gettext_lazy as _\n\nfrom members.models import Member\nfrom events.models import Event\nfrom pushnotifications.models import ScheduledMessage, Category\n\nCOVER_FILENAME = \"cover.jpg\"\n\n\nlogger = logging.getLogger(__name__)\n\n\ndef photo_uploadto(instance, filename):\n    \"\"\"Get path of file to upload to.\"\"\"\n    num = instance.album.photo_set.count()\n    extension = os.path.splitext(filename)[1]\n    new_filename = str(num).zfill(4) + extension\n    return os.path.join(Album.photosdir, instance.album.dirname, new_filename)\n\n\nclass Photo(models.Model):\n    \"\"\"Model for a Photo object.\"\"\"\n\n    album = models.ForeignKey(\n        \"Album\", on_delete=models.CASCADE, verbose_name=_(\"album\")\n    )\n\n    file = models.ImageField(_(\"file\"), upload_to=photo_uploadto)\n\n    rotation = models.IntegerField(\n        verbose_name=_(\"rotation\"),\n        default=0,\n        choices=((x, x) for x in (0, 90, 180, 270)),\n        help_text=_(\"This does not modify the original image file.\"),\n    )\n\n    hidden = models.BooleanField(_(\"hidden\"), default=False)\n\n    _digest = models.CharField(\"digest\", max_length=40,)\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Initialize Photo object and set the file if it exists.\"\"\"\n        super().__init__(*args, **kwargs)\n        if self.file:\n            self.original_file = self.file.path\n        else:\n            self.original_file = \"\"\n\n    def __str__(self):\n        \"\"\"Return the filename of a Photo object.\"\"\"\n        return os.path.basename(self.file.name)\n\n    class Meta:\n        \"\"\"Meta class for Photo.\"\"\"\n\n        ordering = (\"file\",)\n\n\nclass Album(models.Model):\n    \"\"\"Model for Album objects.\"\"\"\n\n    title = models.CharField(\n        _(\"title\"),\n        blank=True,\n        max_length=200,\n        help_text=_(\"Leave empty to take over the title of the event\"),\n    )\n\n    dirname = models.CharField(verbose_name=_(\"directory name\"), max_length=200,)\n\n    date = models.DateField(\n        verbose_name=_(\"date\"),\n        blank=True,\n        help_text=_(\"Leave empty to take over the date of the event\"),\n    )\n\n    slug = models.SlugField(verbose_name=_(\"slug\"), unique=True,)\n\n    hidden = models.BooleanField(verbose_name=_(\"hidden\"), default=False)\n\n    new_album_notification = models.ForeignKey(\n        ScheduledMessage, on_delete=models.deletion.SET_NULL, blank=True, null=True\n    )\n\n    event = models.ForeignKey(Event, on_delete=models.SET_NULL, blank=True, null=True)\n\n    _cover = models.OneToOneField(\n        Photo,\n        on_delete=models.SET_NULL,\n        blank=True,\n        null=True,\n        related_name=\"covered_album\",\n        verbose_name=_(\"cover image\"),\n    )\n\n    shareable = models.BooleanField(verbose_name=_(\"shareable\"), default=False)\n\n    photosdir = \"photos\"\n    photospath = os.path.join(settings.MEDIA_ROOT, photosdir)\n\n    @cached_property\n    def cover(self):\n        \"\"\"Return cover of Album.\n\n        If a cover is not set, return a random photo or None if there are no photos.\n        \"\"\"\n        cover = None\n        if self._cover is not None:\n            return self._cover\n        if self.photo_set.exists():\n            random.seed(self.dirname)\n            cover = random.choice(self.photo_set.all())\n        return cover\n\n    def __str__(self):\n        \"\"\"Get string representation of Album.\"\"\"\n        return \"{} {}\".format(self.date.strftime(\"%Y-%m-%d\"), self.title)\n\n    def get_absolute_url(self):\n        \"\"\"Get url of Album.\"\"\"\n        return reverse(\"photos:album\", args=[str(self.slug)])\n\n    def clean(self):\n        super().clean()\n        errors = {}\n\n        if not self.title and not self.event:\n            errors.update(\n                {\"title\": _(\"This field is required if there is no event selected.\")}\n            )\n\n        if not self.date and not self.event:\n            errors.update(\n                {\"date\": _(\"This field is required if there is no event selected.\")}\n            )\n\n        if errors:\n            raise ValidationError(errors)\n\n    def save(self, **kwargs):\n        \"\"\"Save album and send appropriate notifications.\"\"\"\n        # dirname is only set for new objects, to avoid ever changing it\n        if self.pk is None:\n            self.dirname = self.slug\n\n        if not self.title and self.event:\n            self.title = self.event.title_en\n\n        if not self.date:\n            self.date = self.event.start.date()\n\n        if not self.hidden and (\n            self.new_album_notification is None or not self.new_album_notification.sent\n        ):\n            new_album_notification_time = timezone.now() + timezone.timedelta(hours=1)\n            new_album_notification = ScheduledMessage()\n\n            if (\n                self.new_album_notification is not None\n                and not self.new_album_notification.sent\n            ):\n                new_album_notification = self.new_album_notification\n\n            new_album_notification.title_en = \"New album uploaded\"\n            new_album_notification.body_en = (\n                f\"A new photo album '{self.title}' has just been uploaded\"\n            )\n            new_album_notification.category = Category.objects.get(key=Category.PHOTO)\n            new_album_notification.url = f\"{settings.BASE_URL}{self.get_absolute_url()}\"\n            new_album_notification.time = new_album_notification_time\n            new_album_notification.save()\n            self.new_album_notification = new_album_notification\n            self.new_album_notification.users.set(Member.current_members.all())\n        elif (\n            self.hidden\n            and self.new_album_notification is not None\n            and not self.new_album_notification.sent\n        ):\n            existing_notification = self.new_album_notification\n            self.new_album_notification = None\n            existing_notification.delete()\n\n        super().save(**kwargs)\n\n    @property\n    def access_token(self):\n        \"\"\"Return access token for album.\"\"\"\n        return hashlib.sha256(\n            \"{}album{}\".format(settings.SECRET_KEY, self.pk).encode(\"utf-8\")\n        ).hexdigest()\n\n    class Meta:\n        \"\"\"Meta class for Album.\"\"\"\n\n        ordering = (\"-date\", \"title\")\n", "path": "website/photos/models.py"}], "after_files": [{"content": "import hashlib\nimport logging\nimport os\nimport random\n\nfrom django.conf import settings\nfrom django.core.exceptions import ValidationError\nfrom django.db import models\nfrom django.urls import reverse\nfrom django.utils import timezone\nfrom django.utils.functional import cached_property\nfrom django.utils.translation import gettext_lazy as _\n\nfrom members.models import Member\nfrom events.models import Event\nfrom pushnotifications.models import ScheduledMessage, Category\n\nCOVER_FILENAME = \"cover.jpg\"\n\n\nlogger = logging.getLogger(__name__)\n\n\ndef photo_uploadto(instance, filename):\n    \"\"\"Get path of file to upload to.\"\"\"\n    num = instance.album.photo_set.count()\n    extension = os.path.splitext(filename)[1]\n    new_filename = str(num).zfill(4) + extension\n    return os.path.join(Album.photosdir, instance.album.dirname, new_filename)\n\n\nclass Photo(models.Model):\n    \"\"\"Model for a Photo object.\"\"\"\n\n    album = models.ForeignKey(\n        \"Album\", on_delete=models.CASCADE, verbose_name=_(\"album\")\n    )\n\n    file = models.ImageField(_(\"file\"), upload_to=photo_uploadto)\n\n    rotation = models.IntegerField(\n        verbose_name=_(\"rotation\"),\n        default=0,\n        choices=((x, x) for x in (0, 90, 180, 270)),\n        help_text=_(\"This does not modify the original image file.\"),\n    )\n\n    hidden = models.BooleanField(_(\"hidden\"), default=False)\n\n    _digest = models.CharField(\"digest\", max_length=40,)\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Initialize Photo object and set the file if it exists.\"\"\"\n        super().__init__(*args, **kwargs)\n        if self.file:\n            self.original_file = self.file.path\n        else:\n            self.original_file = \"\"\n\n    def __str__(self):\n        \"\"\"Return the filename of a Photo object.\"\"\"\n        return os.path.basename(self.file.name)\n\n    class Meta:\n        \"\"\"Meta class for Photo.\"\"\"\n\n        ordering = (\"file\",)\n\n\nclass Album(models.Model):\n    \"\"\"Model for Album objects.\"\"\"\n\n    title = models.CharField(\n        _(\"title\"),\n        blank=True,\n        max_length=200,\n        help_text=_(\"Leave empty to take over the title of the event\"),\n    )\n\n    dirname = models.CharField(verbose_name=_(\"directory name\"), max_length=200,)\n\n    date = models.DateField(\n        verbose_name=_(\"date\"),\n        blank=True,\n        help_text=_(\"Leave empty to take over the date of the event\"),\n    )\n\n    slug = models.SlugField(verbose_name=_(\"slug\"), unique=True,)\n\n    hidden = models.BooleanField(verbose_name=_(\"hidden\"), default=False)\n\n    new_album_notification = models.ForeignKey(\n        ScheduledMessage, on_delete=models.deletion.SET_NULL, blank=True, null=True\n    )\n\n    event = models.ForeignKey(Event, on_delete=models.SET_NULL, blank=True, null=True)\n\n    _cover = models.OneToOneField(\n        Photo,\n        on_delete=models.SET_NULL,\n        blank=True,\n        null=True,\n        related_name=\"covered_album\",\n        verbose_name=_(\"cover image\"),\n    )\n\n    shareable = models.BooleanField(verbose_name=_(\"shareable\"), default=False)\n\n    photosdir = \"photos\"\n    photospath = os.path.join(settings.MEDIA_ROOT, photosdir)\n\n    @cached_property\n    def cover(self):\n        \"\"\"Return cover of Album.\n\n        If a cover is not set, return a random photo or None if there are no photos.\n        \"\"\"\n        cover = None\n        if self._cover is not None:\n            return self._cover\n        if self.photo_set.exists():\n            random.seed(self.dirname)\n            cover = random.choice(self.photo_set.all())\n        return cover\n\n    def __str__(self):\n        \"\"\"Get string representation of Album.\"\"\"\n        return \"{} {}\".format(self.date.strftime(\"%Y-%m-%d\"), self.title)\n\n    def get_absolute_url(self):\n        \"\"\"Get url of Album.\"\"\"\n        return reverse(\"photos:album\", args=[str(self.slug)])\n\n    def clean(self):\n        super().clean()\n        errors = {}\n\n        if not self.title and not self.event:\n            errors.update(\n                {\"title\": _(\"This field is required if there is no event selected.\")}\n            )\n\n        if not self.date and not self.event:\n            errors.update(\n                {\"date\": _(\"This field is required if there is no event selected.\")}\n            )\n\n        if errors:\n            raise ValidationError(errors)\n\n    def save(self, **kwargs):\n        \"\"\"Save album and send appropriate notifications.\"\"\"\n        # dirname is only set for new objects, to avoid ever changing it\n        if self.pk is None:\n            self.dirname = self.slug\n\n        if not self.title and self.event:\n            self.title = self.event.title\n\n        if not self.date:\n            self.date = self.event.start.date()\n\n        if not self.hidden and (\n            self.new_album_notification is None or not self.new_album_notification.sent\n        ):\n            new_album_notification_time = timezone.now() + timezone.timedelta(hours=1)\n            new_album_notification = ScheduledMessage()\n\n            if (\n                self.new_album_notification is not None\n                and not self.new_album_notification.sent\n            ):\n                new_album_notification = self.new_album_notification\n\n            new_album_notification.title_en = \"New album uploaded\"\n            new_album_notification.body_en = (\n                f\"A new photo album '{self.title}' has just been uploaded\"\n            )\n            new_album_notification.category = Category.objects.get(key=Category.PHOTO)\n            new_album_notification.url = f\"{settings.BASE_URL}{self.get_absolute_url()}\"\n            new_album_notification.time = new_album_notification_time\n            new_album_notification.save()\n            self.new_album_notification = new_album_notification\n            self.new_album_notification.users.set(Member.current_members.all())\n        elif (\n            self.hidden\n            and self.new_album_notification is not None\n            and not self.new_album_notification.sent\n        ):\n            existing_notification = self.new_album_notification\n            self.new_album_notification = None\n            existing_notification.delete()\n\n        super().save(**kwargs)\n\n    @property\n    def access_token(self):\n        \"\"\"Return access token for album.\"\"\"\n        return hashlib.sha256(\n            \"{}album{}\".format(settings.SECRET_KEY, self.pk).encode(\"utf-8\")\n        ).hexdigest()\n\n    class Meta:\n        \"\"\"Meta class for Album.\"\"\"\n\n        ordering = (\"-date\", \"title\")\n", "path": "website/photos/models.py"}]}