We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
DataError: value too long for type character varying(100)
Sentry Issue: [MEINBERLIN-DEV-2Z](https://sentry.liqd.net/organizations/liqd/issues/1357/?referrer=github_integration)

```
StringDataRightTruncation: value too long for type character varying(100)

  File "django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)

DataError: value too long for type character varying(100)

(29 additional frame(s) were not displayed)
...
  File "django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)

Internal Server Error: /api/organisations/1/bplan/
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `meinberlin/apps/bplan/serializers.py`
Content:
```
1 import datetime
2 import imghdr
3 import posixpath
4 import tempfile
5 from urllib.parse import urlparse
6 
7 import requests
8 from django.apps import apps
9 from django.conf import settings
10 from django.contrib.sites.models import Site
11 from django.core.exceptions import ValidationError
12 from django.core.files.images import ImageFile
13 from django.urls import reverse
14 from django.utils import timezone
15 from django.utils.translation import ugettext as _
16 from rest_framework import serializers
17 
18 from adhocracy4.dashboard import components
19 from adhocracy4.dashboard import signals as a4dashboard_signals
20 from adhocracy4.images.validators import validate_image
21 from adhocracy4.modules import models as module_models
22 from adhocracy4.phases import models as phase_models
23 from adhocracy4.projects import models as project_models
24 
25 from .models import Bplan
26 from .phases import StatementPhase
27 
28 BPLAN_EMBED = '<iframe height="500" style="width: 100%; min-height: 300px; ' \
29               'max-height: 100vh" src="{}" frameborder="0"></iframe>'
30 DOWNLOAD_IMAGE_SIZE_LIMIT_BYTES = 10 * 1024 * 1024
31 
32 
33 class BplanSerializer(serializers.ModelSerializer):
34     id = serializers.IntegerField(required=False)
35 
36     # make write_only for consistency  reasons
37     start_date = serializers.DateTimeField(write_only=True)
38     end_date = serializers.DateTimeField(write_only=True)
39     image_url = serializers.URLField(required=False, write_only=True)
40     image_copyright = serializers.CharField(required=False, write_only=True,
41                                             source='tile_image_copyright',
42                                             allow_blank=True,
43                                             max_length=120)
44     embed_code = serializers.SerializerMethodField()
45 
46     class Meta:
47         model = Bplan
48         fields = (
49             'id', 'name', 'identifier', 'description', 'url',
50             'office_worker_email', 'is_draft', 'start_date', 'end_date',
51             'image_url', 'image_copyright', 'embed_code'
52         )
53         extra_kwargs = {
54             # write_only for consistency reasons
55             'is_draft': {'default': False, 'write_only': True},
56             'name': {'write_only': True},
57             'description': {'write_only': True},
58             'url': {'write_only': True},
59             'office_worker_email': {'write_only': True},
60             'identifier': {'write_only': True}
61         }
62 
63     def create(self, validated_data):
64         orga_pk = self._context.get('organisation_pk', None)
65         orga_model = apps.get_model(settings.A4_ORGANISATIONS_MODEL)
66         orga = orga_model.objects.get(pk=orga_pk)
67         validated_data['organisation'] = orga
68 
69         start_date = validated_data['start_date']
70         end_date = validated_data['end_date']
71 
72         image_url = validated_data.pop('image_url', None)
73         if image_url:
74             validated_data['tile_image'] = \
75                 self._download_image_from_url(image_url)
76 
77         bplan = super().create(validated_data)
78         self._create_module_and_phase(bplan, start_date, end_date)
79         self._send_project_created_signal(bplan)
80         return bplan
81 
82     def _create_module_and_phase(self, bplan, start_date, end_date):
83         module = module_models.Module.objects.create(
84             name=bplan.slug + '_module',
85             weight=1,
86             project=bplan,
87         )
88 
89         phase_content = StatementPhase()
90         phase_models.Phase.objects.create(
91             name=_('Bplan statement phase'),
92             description=_('Bplan statement phase'),
93             type=phase_content.identifier,
94             module=module,
95             start_date=start_date,
96             end_date=end_date
97         )
98 
99     def update(self, instance, validated_data):
100         start_date = validated_data.get('start_date', None)
101         end_date = validated_data.get('end_date', None)
102         if start_date or end_date:
103             self._update_phase(instance, start_date, end_date)
104             if end_date and end_date > timezone.localtime(timezone.now()):
105                 instance.is_archived = False
106 
107         image_url = validated_data.pop('image_url', None)
108         if image_url:
109             validated_data['tile_image'] = \
110                 self._download_image_from_url(image_url)
111 
112         instance = super().update(instance, validated_data)
113 
114         self._send_component_updated_signal(instance)
115         return instance
116 
117     def _update_phase(self, bplan, start_date, end_date):
118         module = module_models.Module.objects.get(project=bplan)
119         phase = phase_models.Phase.objects.get(module=module)
120         if start_date:
121             phase.start_date = start_date
122         if end_date:
123             phase.end_date = end_date
124         phase.save()
125 
126     def get_embed_code(self, bplan):
127         url = self._get_absolute_url(bplan)
128         embed = BPLAN_EMBED.format(url)
129         return embed
130 
131     def _get_absolute_url(self, bplan):
132         site_url = Site.objects.get_current().domain
133         embed_url = reverse('embed-project', kwargs={'slug': bplan.slug, })
134         url = 'https://{}{}'.format(site_url, embed_url)
135         return url
136 
137     def _download_image_from_url(self, url):
138         parsed_url = urlparse(url)
139         file_name = None
140         try:
141             r = requests.get(url, stream=True, timeout=10)
142             downloaded_bytes = 0
143             with tempfile.TemporaryFile() as f:
144                 for chunk in r.iter_content(chunk_size=1024):
145                     downloaded_bytes += len(chunk)
146                     if downloaded_bytes > DOWNLOAD_IMAGE_SIZE_LIMIT_BYTES:
147                         raise serializers.ValidationError(
148                             'Image too large to download {}'.format(url))
149                     if chunk:
150                         f.write(chunk)
151                 file_name = self._generate_image_filename(parsed_url.path, f)
152                 self._image_storage.save(file_name, f)
153         except Exception:
154             if file_name:
155                 self._image_storage.delete(file_name)
156             raise serializers.ValidationError(
157                 'Failed to download image {}'.format(url))
158 
159         try:
160             self._validate_image(file_name)
161         except ValidationError as e:
162             self._image_storage.delete(file_name)
163             raise serializers.ValidationError(e)
164 
165         return file_name
166 
167     def _validate_image(self, file_name):
168         image_file = self._image_storage.open(file_name, 'rb')
169         image = ImageFile(image_file, file_name)
170         config = settings.IMAGE_ALIASES.get('*', {})
171         config.update(settings.IMAGE_ALIASES['tileimage'])
172         validate_image(image, **config)
173 
174     @property
175     def _image_storage(self):
176         return project_models.Project._meta.get_field('tile_image').storage
177 
178     @property
179     def _image_upload_to(self):
180         return project_models.Project._meta.get_field('tile_image').upload_to
181 
182     def _generate_image_filename(self, url_path, file):
183         if callable(self._image_upload_to):
184             raise Exception('Callable upload_to fields are not supported')
185 
186         root_path, extension = posixpath.splitext(url_path)
187         if file:
188             # Workaround: imghdr expects the files position on 0
189             file.seek(0)
190             extension = imghdr.what(file) or 'jpeg'
191 
192         basename = posixpath.basename(root_path)
193         if not basename:
194             basename = 'bplan'
195 
196         dirname = datetime.datetime.now().strftime(self._image_upload_to)
197         filename = posixpath.join(dirname, basename + '.' + extension)
198 
199         return self._image_storage.get_available_name(filename)
200 
201     def _send_project_created_signal(self, bplan):
202         a4dashboard_signals.project_created.send(
203             sender=self.__class__,
204             project=bplan,
205             user=self.context['request'].user
206         )
207 
208     def _send_component_updated_signal(self, bplan):
209         component = components.projects['bplan']
210         a4dashboard_signals.project_component_updated.send(
211             sender=self.__class__,
212             project=bplan,
213             component=component,
214             user=self.context['request'].user
215         )
216
```
--- 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/meinberlin/apps/bplan/serializers.py b/meinberlin/apps/bplan/serializers.py
--- a/meinberlin/apps/bplan/serializers.py
+++ b/meinberlin/apps/bplan/serializers.py
@@ -36,11 +36,18 @@
     # make write_only for consistency  reasons
     start_date = serializers.DateTimeField(write_only=True)
     end_date = serializers.DateTimeField(write_only=True)
-    image_url = serializers.URLField(required=False, write_only=True)
-    image_copyright = serializers.CharField(required=False, write_only=True,
-                                            source='tile_image_copyright',
-                                            allow_blank=True,
-                                            max_length=120)
+    image_url = serializers.URLField(
+        required=False,
+        write_only=True,
+        max_length=(project_models.Project._meta.
+                    get_field('tile_image').max_length))
+    image_copyright = serializers.CharField(
+        required=False,
+        write_only=True,
+        source='tile_image_copyright',
+        allow_blank=True,
+        max_length=(project_models.Project._meta.
+                    get_field('tile_image_copyright').max_length))
     embed_code = serializers.SerializerMethodField()
 
     class Meta:

{"golden_diff": "diff --git a/meinberlin/apps/bplan/serializers.py b/meinberlin/apps/bplan/serializers.py\n--- a/meinberlin/apps/bplan/serializers.py\n+++ b/meinberlin/apps/bplan/serializers.py\n@@ -36,11 +36,18 @@\n     # make write_only for consistency  reasons\n     start_date = serializers.DateTimeField(write_only=True)\n     end_date = serializers.DateTimeField(write_only=True)\n-    image_url = serializers.URLField(required=False, write_only=True)\n-    image_copyright = serializers.CharField(required=False, write_only=True,\n-                                            source='tile_image_copyright',\n-                                            allow_blank=True,\n-                                            max_length=120)\n+    image_url = serializers.URLField(\n+        required=False,\n+        write_only=True,\n+        max_length=(project_models.Project._meta.\n+                    get_field('tile_image').max_length))\n+    image_copyright = serializers.CharField(\n+        required=False,\n+        write_only=True,\n+        source='tile_image_copyright',\n+        allow_blank=True,\n+        max_length=(project_models.Project._meta.\n+                    get_field('tile_image_copyright').max_length))\n     embed_code = serializers.SerializerMethodField()\n \n     class Meta:\n", "issue": "DataError: value too long for type character varying(100)\nSentry Issue: [MEINBERLIN-DEV-2Z](https://sentry.liqd.net/organizations/liqd/issues/1357/?referrer=github_integration)\n\n```\nStringDataRightTruncation: value too long for type character varying(100)\n\n  File \"django/db/backends/utils.py\", line 84, in _execute\n    return self.cursor.execute(sql, params)\n\nDataError: value too long for type character varying(100)\n\n(29 additional frame(s) were not displayed)\n...\n  File \"django/db/backends/utils.py\", line 67, in execute\n    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)\n  File \"django/db/backends/utils.py\", line 76, in _execute_with_wrappers\n    return executor(sql, params, many, context)\n  File \"django/db/backends/utils.py\", line 84, in _execute\n    return self.cursor.execute(sql, params)\n  File \"django/db/utils.py\", line 89, in __exit__\n    raise dj_exc_value.with_traceback(traceback) from exc_value\n  File \"django/db/backends/utils.py\", line 84, in _execute\n    return self.cursor.execute(sql, params)\n\nInternal Server Error: /api/organisations/1/bplan/\n```\n", "before_files": [{"content": "import datetime\nimport imghdr\nimport posixpath\nimport tempfile\nfrom urllib.parse import urlparse\n\nimport requests\nfrom django.apps import apps\nfrom django.conf import settings\nfrom django.contrib.sites.models import Site\nfrom django.core.exceptions import ValidationError\nfrom django.core.files.images import ImageFile\nfrom django.urls import reverse\nfrom django.utils import timezone\nfrom django.utils.translation import ugettext as _\nfrom rest_framework import serializers\n\nfrom adhocracy4.dashboard import components\nfrom adhocracy4.dashboard import signals as a4dashboard_signals\nfrom adhocracy4.images.validators import validate_image\nfrom adhocracy4.modules import models as module_models\nfrom adhocracy4.phases import models as phase_models\nfrom adhocracy4.projects import models as project_models\n\nfrom .models import Bplan\nfrom .phases import StatementPhase\n\nBPLAN_EMBED = '<iframe height=\"500\" style=\"width: 100%; min-height: 300px; ' \\\n              'max-height: 100vh\" src=\"{}\" frameborder=\"0\"></iframe>'\nDOWNLOAD_IMAGE_SIZE_LIMIT_BYTES = 10 * 1024 * 1024\n\n\nclass BplanSerializer(serializers.ModelSerializer):\n    id = serializers.IntegerField(required=False)\n\n    # make write_only for consistency  reasons\n    start_date = serializers.DateTimeField(write_only=True)\n    end_date = serializers.DateTimeField(write_only=True)\n    image_url = serializers.URLField(required=False, write_only=True)\n    image_copyright = serializers.CharField(required=False, write_only=True,\n                                            source='tile_image_copyright',\n                                            allow_blank=True,\n                                            max_length=120)\n    embed_code = serializers.SerializerMethodField()\n\n    class Meta:\n        model = Bplan\n        fields = (\n            'id', 'name', 'identifier', 'description', 'url',\n            'office_worker_email', 'is_draft', 'start_date', 'end_date',\n            'image_url', 'image_copyright', 'embed_code'\n        )\n        extra_kwargs = {\n            # write_only for consistency reasons\n            'is_draft': {'default': False, 'write_only': True},\n            'name': {'write_only': True},\n            'description': {'write_only': True},\n            'url': {'write_only': True},\n            'office_worker_email': {'write_only': True},\n            'identifier': {'write_only': True}\n        }\n\n    def create(self, validated_data):\n        orga_pk = self._context.get('organisation_pk', None)\n        orga_model = apps.get_model(settings.A4_ORGANISATIONS_MODEL)\n        orga = orga_model.objects.get(pk=orga_pk)\n        validated_data['organisation'] = orga\n\n        start_date = validated_data['start_date']\n        end_date = validated_data['end_date']\n\n        image_url = validated_data.pop('image_url', None)\n        if image_url:\n            validated_data['tile_image'] = \\\n                self._download_image_from_url(image_url)\n\n        bplan = super().create(validated_data)\n        self._create_module_and_phase(bplan, start_date, end_date)\n        self._send_project_created_signal(bplan)\n        return bplan\n\n    def _create_module_and_phase(self, bplan, start_date, end_date):\n        module = module_models.Module.objects.create(\n            name=bplan.slug + '_module',\n            weight=1,\n            project=bplan,\n        )\n\n        phase_content = StatementPhase()\n        phase_models.Phase.objects.create(\n            name=_('Bplan statement phase'),\n            description=_('Bplan statement phase'),\n            type=phase_content.identifier,\n            module=module,\n            start_date=start_date,\n            end_date=end_date\n        )\n\n    def update(self, instance, validated_data):\n        start_date = validated_data.get('start_date', None)\n        end_date = validated_data.get('end_date', None)\n        if start_date or end_date:\n            self._update_phase(instance, start_date, end_date)\n            if end_date and end_date > timezone.localtime(timezone.now()):\n                instance.is_archived = False\n\n        image_url = validated_data.pop('image_url', None)\n        if image_url:\n            validated_data['tile_image'] = \\\n                self._download_image_from_url(image_url)\n\n        instance = super().update(instance, validated_data)\n\n        self._send_component_updated_signal(instance)\n        return instance\n\n    def _update_phase(self, bplan, start_date, end_date):\n        module = module_models.Module.objects.get(project=bplan)\n        phase = phase_models.Phase.objects.get(module=module)\n        if start_date:\n            phase.start_date = start_date\n        if end_date:\n            phase.end_date = end_date\n        phase.save()\n\n    def get_embed_code(self, bplan):\n        url = self._get_absolute_url(bplan)\n        embed = BPLAN_EMBED.format(url)\n        return embed\n\n    def _get_absolute_url(self, bplan):\n        site_url = Site.objects.get_current().domain\n        embed_url = reverse('embed-project', kwargs={'slug': bplan.slug, })\n        url = 'https://{}{}'.format(site_url, embed_url)\n        return url\n\n    def _download_image_from_url(self, url):\n        parsed_url = urlparse(url)\n        file_name = None\n        try:\n            r = requests.get(url, stream=True, timeout=10)\n            downloaded_bytes = 0\n            with tempfile.TemporaryFile() as f:\n                for chunk in r.iter_content(chunk_size=1024):\n                    downloaded_bytes += len(chunk)\n                    if downloaded_bytes > DOWNLOAD_IMAGE_SIZE_LIMIT_BYTES:\n                        raise serializers.ValidationError(\n                            'Image too large to download {}'.format(url))\n                    if chunk:\n                        f.write(chunk)\n                file_name = self._generate_image_filename(parsed_url.path, f)\n                self._image_storage.save(file_name, f)\n        except Exception:\n            if file_name:\n                self._image_storage.delete(file_name)\n            raise serializers.ValidationError(\n                'Failed to download image {}'.format(url))\n\n        try:\n            self._validate_image(file_name)\n        except ValidationError as e:\n            self._image_storage.delete(file_name)\n            raise serializers.ValidationError(e)\n\n        return file_name\n\n    def _validate_image(self, file_name):\n        image_file = self._image_storage.open(file_name, 'rb')\n        image = ImageFile(image_file, file_name)\n        config = settings.IMAGE_ALIASES.get('*', {})\n        config.update(settings.IMAGE_ALIASES['tileimage'])\n        validate_image(image, **config)\n\n    @property\n    def _image_storage(self):\n        return project_models.Project._meta.get_field('tile_image').storage\n\n    @property\n    def _image_upload_to(self):\n        return project_models.Project._meta.get_field('tile_image').upload_to\n\n    def _generate_image_filename(self, url_path, file):\n        if callable(self._image_upload_to):\n            raise Exception('Callable upload_to fields are not supported')\n\n        root_path, extension = posixpath.splitext(url_path)\n        if file:\n            # Workaround: imghdr expects the files position on 0\n            file.seek(0)\n            extension = imghdr.what(file) or 'jpeg'\n\n        basename = posixpath.basename(root_path)\n        if not basename:\n            basename = 'bplan'\n\n        dirname = datetime.datetime.now().strftime(self._image_upload_to)\n        filename = posixpath.join(dirname, basename + '.' + extension)\n\n        return self._image_storage.get_available_name(filename)\n\n    def _send_project_created_signal(self, bplan):\n        a4dashboard_signals.project_created.send(\n            sender=self.__class__,\n            project=bplan,\n            user=self.context['request'].user\n        )\n\n    def _send_component_updated_signal(self, bplan):\n        component = components.projects['bplan']\n        a4dashboard_signals.project_component_updated.send(\n            sender=self.__class__,\n            project=bplan,\n            component=component,\n            user=self.context['request'].user\n        )\n", "path": "meinberlin/apps/bplan/serializers.py"}], "after_files": [{"content": "import datetime\nimport imghdr\nimport posixpath\nimport tempfile\nfrom urllib.parse import urlparse\n\nimport requests\nfrom django.apps import apps\nfrom django.conf import settings\nfrom django.contrib.sites.models import Site\nfrom django.core.exceptions import ValidationError\nfrom django.core.files.images import ImageFile\nfrom django.urls import reverse\nfrom django.utils import timezone\nfrom django.utils.translation import ugettext as _\nfrom rest_framework import serializers\n\nfrom adhocracy4.dashboard import components\nfrom adhocracy4.dashboard import signals as a4dashboard_signals\nfrom adhocracy4.images.validators import validate_image\nfrom adhocracy4.modules import models as module_models\nfrom adhocracy4.phases import models as phase_models\nfrom adhocracy4.projects import models as project_models\n\nfrom .models import Bplan\nfrom .phases import StatementPhase\n\nBPLAN_EMBED = '<iframe height=\"500\" style=\"width: 100%; min-height: 300px; ' \\\n              'max-height: 100vh\" src=\"{}\" frameborder=\"0\"></iframe>'\nDOWNLOAD_IMAGE_SIZE_LIMIT_BYTES = 10 * 1024 * 1024\n\n\nclass BplanSerializer(serializers.ModelSerializer):\n    id = serializers.IntegerField(required=False)\n\n    # make write_only for consistency  reasons\n    start_date = serializers.DateTimeField(write_only=True)\n    end_date = serializers.DateTimeField(write_only=True)\n    image_url = serializers.URLField(\n        required=False,\n        write_only=True,\n        max_length=(project_models.Project._meta.\n                    get_field('tile_image').max_length))\n    image_copyright = serializers.CharField(\n        required=False,\n        write_only=True,\n        source='tile_image_copyright',\n        allow_blank=True,\n        max_length=(project_models.Project._meta.\n                    get_field('tile_image_copyright').max_length))\n    embed_code = serializers.SerializerMethodField()\n\n    class Meta:\n        model = Bplan\n        fields = (\n            'id', 'name', 'identifier', 'description', 'url',\n            'office_worker_email', 'is_draft', 'start_date', 'end_date',\n            'image_url', 'image_copyright', 'embed_code'\n        )\n        extra_kwargs = {\n            # write_only for consistency reasons\n            'is_draft': {'default': False, 'write_only': True},\n            'name': {'write_only': True},\n            'description': {'write_only': True},\n            'url': {'write_only': True},\n            'office_worker_email': {'write_only': True},\n            'identifier': {'write_only': True}\n        }\n\n    def create(self, validated_data):\n        orga_pk = self._context.get('organisation_pk', None)\n        orga_model = apps.get_model(settings.A4_ORGANISATIONS_MODEL)\n        orga = orga_model.objects.get(pk=orga_pk)\n        validated_data['organisation'] = orga\n\n        start_date = validated_data['start_date']\n        end_date = validated_data['end_date']\n\n        image_url = validated_data.pop('image_url', None)\n        if image_url:\n            validated_data['tile_image'] = \\\n                self._download_image_from_url(image_url)\n\n        bplan = super().create(validated_data)\n        self._create_module_and_phase(bplan, start_date, end_date)\n        self._send_project_created_signal(bplan)\n        return bplan\n\n    def _create_module_and_phase(self, bplan, start_date, end_date):\n        module = module_models.Module.objects.create(\n            name=bplan.slug + '_module',\n            weight=1,\n            project=bplan,\n        )\n\n        phase_content = StatementPhase()\n        phase_models.Phase.objects.create(\n            name=_('Bplan statement phase'),\n            description=_('Bplan statement phase'),\n            type=phase_content.identifier,\n            module=module,\n            start_date=start_date,\n            end_date=end_date\n        )\n\n    def update(self, instance, validated_data):\n        start_date = validated_data.get('start_date', None)\n        end_date = validated_data.get('end_date', None)\n        if start_date or end_date:\n            self._update_phase(instance, start_date, end_date)\n            if end_date and end_date > timezone.localtime(timezone.now()):\n                instance.is_archived = False\n\n        image_url = validated_data.pop('image_url', None)\n        if image_url:\n            validated_data['tile_image'] = \\\n                self._download_image_from_url(image_url)\n\n        instance = super().update(instance, validated_data)\n\n        self._send_component_updated_signal(instance)\n        return instance\n\n    def _update_phase(self, bplan, start_date, end_date):\n        module = module_models.Module.objects.get(project=bplan)\n        phase = phase_models.Phase.objects.get(module=module)\n        if start_date:\n            phase.start_date = start_date\n        if end_date:\n            phase.end_date = end_date\n        phase.save()\n\n    def get_embed_code(self, bplan):\n        url = self._get_absolute_url(bplan)\n        embed = BPLAN_EMBED.format(url)\n        return embed\n\n    def _get_absolute_url(self, bplan):\n        site_url = Site.objects.get_current().domain\n        embed_url = reverse('embed-project', kwargs={'slug': bplan.slug, })\n        url = 'https://{}{}'.format(site_url, embed_url)\n        return url\n\n    def _download_image_from_url(self, url):\n        parsed_url = urlparse(url)\n        file_name = None\n        try:\n            r = requests.get(url, stream=True, timeout=10)\n            downloaded_bytes = 0\n            with tempfile.TemporaryFile() as f:\n                for chunk in r.iter_content(chunk_size=1024):\n                    downloaded_bytes += len(chunk)\n                    if downloaded_bytes > DOWNLOAD_IMAGE_SIZE_LIMIT_BYTES:\n                        raise serializers.ValidationError(\n                            'Image too large to download {}'.format(url))\n                    if chunk:\n                        f.write(chunk)\n                file_name = self._generate_image_filename(parsed_url.path, f)\n                self._image_storage.save(file_name, f)\n        except Exception:\n            if file_name:\n                self._image_storage.delete(file_name)\n            raise serializers.ValidationError(\n                'Failed to download image {}'.format(url))\n\n        try:\n            self._validate_image(file_name)\n        except ValidationError as e:\n            self._image_storage.delete(file_name)\n            raise serializers.ValidationError(e)\n\n        return file_name\n\n    def _validate_image(self, file_name):\n        image_file = self._image_storage.open(file_name, 'rb')\n        image = ImageFile(image_file, file_name)\n        config = settings.IMAGE_ALIASES.get('*', {})\n        config.update(settings.IMAGE_ALIASES['tileimage'])\n        validate_image(image, **config)\n\n    @property\n    def _image_storage(self):\n        return project_models.Project._meta.get_field('tile_image').storage\n\n    @property\n    def _image_upload_to(self):\n        return project_models.Project._meta.get_field('tile_image').upload_to\n\n    def _generate_image_filename(self, url_path, file):\n        if callable(self._image_upload_to):\n            raise Exception('Callable upload_to fields are not supported')\n\n        root_path, extension = posixpath.splitext(url_path)\n        if file:\n            # Workaround: imghdr expects the files position on 0\n            file.seek(0)\n            extension = imghdr.what(file) or 'jpeg'\n\n        basename = posixpath.basename(root_path)\n        if not basename:\n            basename = 'bplan'\n\n        dirname = datetime.datetime.now().strftime(self._image_upload_to)\n        filename = posixpath.join(dirname, basename + '.' + extension)\n\n        return self._image_storage.get_available_name(filename)\n\n    def _send_project_created_signal(self, bplan):\n        a4dashboard_signals.project_created.send(\n            sender=self.__class__,\n            project=bplan,\n            user=self.context['request'].user\n        )\n\n    def _send_component_updated_signal(self, bplan):\n        component = components.projects['bplan']\n        a4dashboard_signals.project_component_updated.send(\n            sender=self.__class__,\n            project=bplan,\n            component=component,\n            user=self.context['request'].user\n        )\n", "path": "meinberlin/apps/bplan/serializers.py"}]}