We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
single module project without timeline is missing any discription
my single module project [https://meinberlin-dev.liqd.net/projects/schillerkasse-ihre-kiezkasse-fur-den-schillerkiez/](url) which is module Kiezkasse should have a phase information. It is currently running.

![Bildschirmfoto 2019-07-05 um 14 17 04](https://user-images.githubusercontent.com/35491681/60721991-e1acfa80-9f2f-11e9-950f-cf28dd3e7645.png)


--- 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/contrib/mixins.py`
Content:
```
1 from django import forms
2 from django.db.models import Max
3 from django.db.models import Min
4 from django.db.models import Q
5 from django.urls import resolve
6 from django.utils.translation import ugettext_lazy as _
7 from django.views import generic
8 
9 from adhocracy4.modules.models import Module
10 
11 RIGHT_OF_USE_LABEL = _('I hereby confirm that the copyrights for this '
12                        'photo are with me or that I have received '
13                        'rights of use from the author. I also confirm '
14                        'that the privacy rights of depicted third persons '
15                        'are not violated. ')
16 
17 
18 class DynamicChoicesMixin(object):
19     """Dynamic choices mixin.
20 
21     Add callable functionality to filters that support the ``choices``
22     argument. If the ``choices`` is callable, then it **must** accept the
23     ``view`` object as a single argument.
24     The ``view`` object may be None if the parent FilterSet is not class based.
25 
26     This is useful for dymanic ``choices`` determined properties on the
27     ``view`` object.
28     """
29 
30     def __init__(self, *args, **kwargs):
31         self.choices = kwargs.pop('choices')
32         super().__init__(*args, **kwargs)
33 
34     def get_choices(self, view):
35         choices = self.choices
36 
37         if callable(choices):
38             return choices(view)
39         return choices
40 
41     @property
42     def field(self):
43         choices = self.get_choices(getattr(self, 'view', None))
44 
45         if choices is not None:
46             self.extra['choices'] = choices
47 
48         return super(DynamicChoicesMixin, self).field
49 
50 
51 class ImageRightOfUseMixin(forms.ModelForm):
52     right_of_use = forms.BooleanField(required=False, label=RIGHT_OF_USE_LABEL)
53 
54     def __init__(self, *args, **kwargs):
55         super().__init__(*args, **kwargs)
56         if self.instance.image:
57             self.initial['right_of_use'] = True
58 
59     def clean(self):
60         cleaned_data = super().clean()
61         image = cleaned_data.get('image')
62         right_of_use = cleaned_data.get('right_of_use')
63         if image and not right_of_use:
64             self.add_error('right_of_use',
65                            _("You want to upload an image. "
66                              "Please check that you have the "
67                              "right of use for the image."))
68 
69 
70 class ModuleClusterMixin:
71 
72     def _get_module_dict(self, count, start_date, end_date):
73         return {
74             'count': count,
75             'date': start_date,
76             'end_date': end_date,
77             'modules': []
78         }
79 
80     def get_module_clusters(self, modules):
81         modules = modules\
82             .exclude(Q(start_date=None) | Q(end_date=None))
83         clusters = []
84         try:
85             start_date = modules.first().start_date
86             end_date = modules.first().end_date
87             count = 1
88             first_cluster = self._get_module_dict(
89                 count, start_date, end_date)
90             first_cluster['modules'].append(modules.first())
91             current_cluster = first_cluster
92             clusters.append(first_cluster)
93 
94             for module in modules[1:]:
95                 if module.start_date > end_date:
96                     start_date = module.start_date
97                     end_date = module.end_date
98                     count += 1
99                     next_cluster = self._get_module_dict(
100                         count, start_date, end_date)
101                     next_cluster['modules'].append(module)
102                     current_cluster = next_cluster
103                     clusters.append(next_cluster)
104                 else:
105                     current_cluster['modules'].append(module)
106                     if module.end_date > end_date:
107                         end_date = module.end_date
108                         current_cluster['end_date'] = end_date
109         except AttributeError:
110             return clusters
111         if len(clusters) == 1:
112             clusters[0]['title'] = _('Online Participation')
113         return clusters
114 
115 
116 class DisplayProjectOrModuleMixin(generic.base.ContextMixin,
117                                   ModuleClusterMixin):
118 
119     def module_clusters(self, modules):
120         return super().get_module_clusters(modules)
121 
122     @property
123     def url_name(self):
124         return resolve(self.request.path_info).url_name
125 
126     @property
127     def other_modules(self):
128         modules = Module.objects.filter(project=self.project)\
129             .annotate(start_date=Min('phase__start_date'))\
130             .annotate(end_date=Max('phase__end_date'))\
131             .order_by('start_date')
132 
133         for cluster in self.module_clusters(modules):
134             if self.module in cluster['modules']:
135                 idx = cluster['modules'].index(self.module)
136                 modules = cluster['modules']
137                 return modules, idx
138         return []
139 
140     @property
141     def extends(self):
142         if self.url_name == 'module-detail':
143             return 'a4modules/module_detail.html'
144         return 'meinberlin_projects/project_detail.html'
145 
146     def get_context_data(self, **kwargs):
147         context = super().get_context_data(**kwargs)
148         context['url_name'] = self.url_name
149         context['extends'] = self.extends
150         if self.url_name == 'module-detail':
151             cluster, idx = self.other_modules
152             next_module = None
153             previous_module = None
154             try:
155                 next_module = cluster[idx + 1]
156             except IndexError:
157                 pass
158             try:
159                 previous_module = cluster[idx - 1]
160             except IndexError:
161                 pass
162             context['other_modules'] = cluster
163             context['index'] = idx + 1
164             context['next'] = next_module
165             context['previous'] = previous_module
166         return context
167
```
--- 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/contrib/mixins.py b/meinberlin/apps/contrib/mixins.py
--- a/meinberlin/apps/contrib/mixins.py
+++ b/meinberlin/apps/contrib/mixins.py
@@ -156,7 +156,8 @@
             except IndexError:
                 pass
             try:
-                previous_module = cluster[idx - 1]
+                if idx > 0:
+                    previous_module = cluster[idx - 1]
             except IndexError:
                 pass
             context['other_modules'] = cluster

{"golden_diff": "diff --git a/meinberlin/apps/contrib/mixins.py b/meinberlin/apps/contrib/mixins.py\n--- a/meinberlin/apps/contrib/mixins.py\n+++ b/meinberlin/apps/contrib/mixins.py\n@@ -156,7 +156,8 @@\n             except IndexError:\n                 pass\n             try:\n-                previous_module = cluster[idx - 1]\n+                if idx > 0:\n+                    previous_module = cluster[idx - 1]\n             except IndexError:\n                 pass\n             context['other_modules'] = cluster\n", "issue": "single module project without timeline is missing any discription\nmy single module project [https://meinberlin-dev.liqd.net/projects/schillerkasse-ihre-kiezkasse-fur-den-schillerkiez/](url) which is module Kiezkasse should have a phase information. It is currently running.\r\n\r\n![Bildschirmfoto 2019-07-05 um 14 17 04](https://user-images.githubusercontent.com/35491681/60721991-e1acfa80-9f2f-11e9-950f-cf28dd3e7645.png)\r\n\n", "before_files": [{"content": "from django import forms\nfrom django.db.models import Max\nfrom django.db.models import Min\nfrom django.db.models import Q\nfrom django.urls import resolve\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.views import generic\n\nfrom adhocracy4.modules.models import Module\n\nRIGHT_OF_USE_LABEL = _('I hereby confirm that the copyrights for this '\n                       'photo are with me or that I have received '\n                       'rights of use from the author. I also confirm '\n                       'that the privacy rights of depicted third persons '\n                       'are not violated. ')\n\n\nclass DynamicChoicesMixin(object):\n    \"\"\"Dynamic choices mixin.\n\n    Add callable functionality to filters that support the ``choices``\n    argument. If the ``choices`` is callable, then it **must** accept the\n    ``view`` object as a single argument.\n    The ``view`` object may be None if the parent FilterSet is not class based.\n\n    This is useful for dymanic ``choices`` determined properties on the\n    ``view`` object.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.choices = kwargs.pop('choices')\n        super().__init__(*args, **kwargs)\n\n    def get_choices(self, view):\n        choices = self.choices\n\n        if callable(choices):\n            return choices(view)\n        return choices\n\n    @property\n    def field(self):\n        choices = self.get_choices(getattr(self, 'view', None))\n\n        if choices is not None:\n            self.extra['choices'] = choices\n\n        return super(DynamicChoicesMixin, self).field\n\n\nclass ImageRightOfUseMixin(forms.ModelForm):\n    right_of_use = forms.BooleanField(required=False, label=RIGHT_OF_USE_LABEL)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self.instance.image:\n            self.initial['right_of_use'] = True\n\n    def clean(self):\n        cleaned_data = super().clean()\n        image = cleaned_data.get('image')\n        right_of_use = cleaned_data.get('right_of_use')\n        if image and not right_of_use:\n            self.add_error('right_of_use',\n                           _(\"You want to upload an image. \"\n                             \"Please check that you have the \"\n                             \"right of use for the image.\"))\n\n\nclass ModuleClusterMixin:\n\n    def _get_module_dict(self, count, start_date, end_date):\n        return {\n            'count': count,\n            'date': start_date,\n            'end_date': end_date,\n            'modules': []\n        }\n\n    def get_module_clusters(self, modules):\n        modules = modules\\\n            .exclude(Q(start_date=None) | Q(end_date=None))\n        clusters = []\n        try:\n            start_date = modules.first().start_date\n            end_date = modules.first().end_date\n            count = 1\n            first_cluster = self._get_module_dict(\n                count, start_date, end_date)\n            first_cluster['modules'].append(modules.first())\n            current_cluster = first_cluster\n            clusters.append(first_cluster)\n\n            for module in modules[1:]:\n                if module.start_date > end_date:\n                    start_date = module.start_date\n                    end_date = module.end_date\n                    count += 1\n                    next_cluster = self._get_module_dict(\n                        count, start_date, end_date)\n                    next_cluster['modules'].append(module)\n                    current_cluster = next_cluster\n                    clusters.append(next_cluster)\n                else:\n                    current_cluster['modules'].append(module)\n                    if module.end_date > end_date:\n                        end_date = module.end_date\n                        current_cluster['end_date'] = end_date\n        except AttributeError:\n            return clusters\n        if len(clusters) == 1:\n            clusters[0]['title'] = _('Online Participation')\n        return clusters\n\n\nclass DisplayProjectOrModuleMixin(generic.base.ContextMixin,\n                                  ModuleClusterMixin):\n\n    def module_clusters(self, modules):\n        return super().get_module_clusters(modules)\n\n    @property\n    def url_name(self):\n        return resolve(self.request.path_info).url_name\n\n    @property\n    def other_modules(self):\n        modules = Module.objects.filter(project=self.project)\\\n            .annotate(start_date=Min('phase__start_date'))\\\n            .annotate(end_date=Max('phase__end_date'))\\\n            .order_by('start_date')\n\n        for cluster in self.module_clusters(modules):\n            if self.module in cluster['modules']:\n                idx = cluster['modules'].index(self.module)\n                modules = cluster['modules']\n                return modules, idx\n        return []\n\n    @property\n    def extends(self):\n        if self.url_name == 'module-detail':\n            return 'a4modules/module_detail.html'\n        return 'meinberlin_projects/project_detail.html'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['url_name'] = self.url_name\n        context['extends'] = self.extends\n        if self.url_name == 'module-detail':\n            cluster, idx = self.other_modules\n            next_module = None\n            previous_module = None\n            try:\n                next_module = cluster[idx + 1]\n            except IndexError:\n                pass\n            try:\n                previous_module = cluster[idx - 1]\n            except IndexError:\n                pass\n            context['other_modules'] = cluster\n            context['index'] = idx + 1\n            context['next'] = next_module\n            context['previous'] = previous_module\n        return context\n", "path": "meinberlin/apps/contrib/mixins.py"}], "after_files": [{"content": "from django import forms\nfrom django.db.models import Max\nfrom django.db.models import Min\nfrom django.db.models import Q\nfrom django.urls import resolve\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.views import generic\n\nfrom adhocracy4.modules.models import Module\n\nRIGHT_OF_USE_LABEL = _('I hereby confirm that the copyrights for this '\n                       'photo are with me or that I have received '\n                       'rights of use from the author. I also confirm '\n                       'that the privacy rights of depicted third persons '\n                       'are not violated. ')\n\n\nclass DynamicChoicesMixin(object):\n    \"\"\"Dynamic choices mixin.\n\n    Add callable functionality to filters that support the ``choices``\n    argument. If the ``choices`` is callable, then it **must** accept the\n    ``view`` object as a single argument.\n    The ``view`` object may be None if the parent FilterSet is not class based.\n\n    This is useful for dymanic ``choices`` determined properties on the\n    ``view`` object.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.choices = kwargs.pop('choices')\n        super().__init__(*args, **kwargs)\n\n    def get_choices(self, view):\n        choices = self.choices\n\n        if callable(choices):\n            return choices(view)\n        return choices\n\n    @property\n    def field(self):\n        choices = self.get_choices(getattr(self, 'view', None))\n\n        if choices is not None:\n            self.extra['choices'] = choices\n\n        return super(DynamicChoicesMixin, self).field\n\n\nclass ImageRightOfUseMixin(forms.ModelForm):\n    right_of_use = forms.BooleanField(required=False, label=RIGHT_OF_USE_LABEL)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self.instance.image:\n            self.initial['right_of_use'] = True\n\n    def clean(self):\n        cleaned_data = super().clean()\n        image = cleaned_data.get('image')\n        right_of_use = cleaned_data.get('right_of_use')\n        if image and not right_of_use:\n            self.add_error('right_of_use',\n                           _(\"You want to upload an image. \"\n                             \"Please check that you have the \"\n                             \"right of use for the image.\"))\n\n\nclass ModuleClusterMixin:\n\n    def _get_module_dict(self, count, start_date, end_date):\n        return {\n            'count': count,\n            'date': start_date,\n            'end_date': end_date,\n            'modules': []\n        }\n\n    def get_module_clusters(self, modules):\n        modules = modules\\\n            .exclude(Q(start_date=None) | Q(end_date=None))\n        clusters = []\n        try:\n            start_date = modules.first().start_date\n            end_date = modules.first().end_date\n            count = 1\n            first_cluster = self._get_module_dict(\n                count, start_date, end_date)\n            first_cluster['modules'].append(modules.first())\n            current_cluster = first_cluster\n            clusters.append(first_cluster)\n\n            for module in modules[1:]:\n                if module.start_date > end_date:\n                    start_date = module.start_date\n                    end_date = module.end_date\n                    count += 1\n                    next_cluster = self._get_module_dict(\n                        count, start_date, end_date)\n                    next_cluster['modules'].append(module)\n                    current_cluster = next_cluster\n                    clusters.append(next_cluster)\n                else:\n                    current_cluster['modules'].append(module)\n                    if module.end_date > end_date:\n                        end_date = module.end_date\n                        current_cluster['end_date'] = end_date\n        except AttributeError:\n            return clusters\n        if len(clusters) == 1:\n            clusters[0]['title'] = _('Online Participation')\n        return clusters\n\n\nclass DisplayProjectOrModuleMixin(generic.base.ContextMixin,\n                                  ModuleClusterMixin):\n\n    def module_clusters(self, modules):\n        return super().get_module_clusters(modules)\n\n    @property\n    def url_name(self):\n        return resolve(self.request.path_info).url_name\n\n    @property\n    def other_modules(self):\n        modules = Module.objects.filter(project=self.project)\\\n            .annotate(start_date=Min('phase__start_date'))\\\n            .annotate(end_date=Max('phase__end_date'))\\\n            .order_by('start_date')\n\n        for cluster in self.module_clusters(modules):\n            if self.module in cluster['modules']:\n                idx = cluster['modules'].index(self.module)\n                modules = cluster['modules']\n                return modules, idx\n        return []\n\n    @property\n    def extends(self):\n        if self.url_name == 'module-detail':\n            return 'a4modules/module_detail.html'\n        return 'meinberlin_projects/project_detail.html'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['url_name'] = self.url_name\n        context['extends'] = self.extends\n        if self.url_name == 'module-detail':\n            cluster, idx = self.other_modules\n            next_module = None\n            previous_module = None\n            try:\n                next_module = cluster[idx + 1]\n            except IndexError:\n                pass\n            try:\n                if idx > 0:\n                    previous_module = cluster[idx - 1]\n            except IndexError:\n                pass\n            context['other_modules'] = cluster\n            context['index'] = idx + 1\n            context['next'] = next_module\n            context['previous'] = previous_module\n        return context\n", "path": "meinberlin/apps/contrib/mixins.py"}]}