We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Breadcrumb in modul "Priorisierung mit Karte" is saying always "list" 
**URL:** https://meinberlin-dev.liqd.net/maptopicprio/2022-00910/
**user:** any
**expected behaviour:** When coming from map I don't want to get confused by a button which says "list" even though you going back to the map.
**behaviour:** In modul "Priorisierung mit Karte" in the detail view the breadcrumb says always list. When you for example come from the map, you go back to map but breadcrumb says "list".
**important screensize:** -
**device & browser:** mac ff
**Comment/Question:** in the other moduls with ideas/proposals (except Bürger*innenhaushalt), it's saying "Back" ("Zurück") and neither "list" nor "map". Probably related to this issue: https://github.com/liqd/a4-meinberlin/issues/4816

Screenshot?


--- 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/budgeting/views.py`
Content:
```
1 from urllib.parse import parse_qs
2 from urllib.parse import urlparse
3 
4 import django_filters
5 from django.urls import resolve
6 from django.urls import reverse
7 from django.utils.translation import gettext_lazy as _
8 
9 from adhocracy4.categories import filters as category_filters
10 from adhocracy4.exports.views import DashboardExportView
11 from adhocracy4.filters import filters as a4_filters
12 from adhocracy4.labels import filters as label_filters
13 from adhocracy4.modules.predicates import module_is_between_phases
14 from adhocracy4.projects.mixins import DisplayProjectOrModuleMixin
15 from meinberlin.apps.ideas import views as idea_views
16 from meinberlin.apps.moderatorremark.forms import ModeratorRemarkForm
17 from meinberlin.apps.projects.views import ArchivedWidget
18 from meinberlin.apps.votes.forms import TokenForm
19 from meinberlin.apps.votes.models import VotingToken
20 
21 from . import forms
22 from . import models
23 
24 
25 def get_ordering_choices(view):
26     choices = (("-created", _("Most recent")),)
27     if view.module.has_feature("rate", models.Proposal):
28         choices += (("-positive_rating_count", _("Most popular")),)
29     elif view.module.has_feature("support", models.Proposal):
30         choices += (("-positive_rating_count", _("Most support")),)
31     choices += (
32         ("-comment_count", _("Most commented")),
33         ("dailyrandom", _("Random")),
34     )
35     return choices
36 
37 
38 def get_default_ordering(view):
39     if module_is_between_phases(
40         "meinberlin_budgeting:support", "meinberlin_budgeting:voting", view.module
41     ):
42         return "-positive_rating_count"
43     elif (
44         view.module.has_feature("vote", models.Proposal)
45         and view.module.module_has_finished
46     ):
47         return "-token_vote_count"
48     return "dailyrandom"
49 
50 
51 class ProposalFilterSet(a4_filters.DefaultsFilterSet):
52     defaults = {"is_archived": "false"}
53     category = category_filters.CategoryFilter()
54     labels = label_filters.LabelFilter()
55     ordering = a4_filters.DistinctOrderingWithDailyRandomFilter(
56         choices=get_ordering_choices
57     )
58     is_archived = django_filters.BooleanFilter(widget=ArchivedWidget)
59 
60     class Meta:
61         model = models.Proposal
62         fields = ["category", "labels", "is_archived"]
63 
64     def __init__(self, data, *args, **kwargs):
65         self.defaults["ordering"] = get_default_ordering(kwargs["view"])
66         super().__init__(data, *args, **kwargs)
67 
68 
69 class ProposalListView(idea_views.AbstractIdeaListView, DisplayProjectOrModuleMixin):
70     model = models.Proposal
71     filter_set = ProposalFilterSet
72 
73     def has_valid_token_in_session(self, request):
74         """Return whether a valid token is stored in the session.
75 
76         The token is valid if it is valid for the respective module.
77         """
78         if "voting_tokens" in request.session:
79             module_key = str(self.module.id)
80             if module_key in request.session["voting_tokens"]:
81                 return (
82                     VotingToken.get_voting_token_by_hash(
83                         token_hash=request.session["voting_tokens"][module_key],
84                         module=self.module,
85                     )
86                     is not None
87                 )
88         return False
89 
90     def dispatch(self, request, **kwargs):
91         self.mode = request.GET.get("mode", "map")
92         if self.mode == "map":
93             self.paginate_by = 0
94         return super().dispatch(request, **kwargs)
95 
96     def get_queryset(self):
97         return super().get_queryset().filter(module=self.module)
98 
99     def get_context_data(self, **kwargs):
100         if "token_form" not in kwargs:
101             token_form = TokenForm(module_id=self.module.id)
102             kwargs["token_form"] = token_form
103         kwargs["valid_token_present"] = self.has_valid_token_in_session(self.request)
104         return super().get_context_data(**kwargs)
105 
106     def post(self, request, *args, **kwargs):
107         self.object_list = self.get_queryset()
108         token_form = TokenForm(request.POST, module_id=self.module.id)
109         if token_form.is_valid():
110             if "voting_tokens" in request.session:
111                 request.session["voting_tokens"][
112                     str(self.module.id)
113                 ] = token_form.cleaned_data["token"]
114                 request.session.save()
115             else:
116                 request.session["voting_tokens"] = {
117                     str(self.module.id): token_form.cleaned_data["token"]
118                 }
119             kwargs["valid_token_present"] = True
120             self.mode = "list"
121         kwargs["token_form"] = token_form
122         context = super().get_context_data(**kwargs)
123         return self.render_to_response(context)
124 
125 
126 class ProposalDetailView(idea_views.AbstractIdeaDetailView):
127     model = models.Proposal
128     queryset = (
129         models.Proposal.objects.annotate_positive_rating_count()
130         .annotate_negative_rating_count()
131         .annotate_token_vote_count()
132     )
133     permission_required = "meinberlin_budgeting.view_proposal"
134 
135     def get_back(self):
136         """
137         Get last page to return to if was project or module view.
138 
139         To make sure all the filters and the display mode (map or list)
140         are remembered when going back, we check if the referer is a
141         module or project detail view and add the appropriate back url.
142         """
143         if "Referer" in self.request.headers:
144             referer = self.request.headers["Referer"]
145             parsed_url = urlparse(referer)
146             match = resolve(parsed_url.path)
147             if match.url_name == "project-detail" or match.url_name == "module-detail":
148                 back_mode = None
149                 back_string = _("map")
150                 if "mode" in parse_qs(parsed_url.query):
151                     back_mode = parse_qs(parsed_url.query)["mode"][0]
152                     if back_mode == "list":
153                         back_string = _("list")
154                 back_link = referer + "#proposal_{}".format(self.object.id)
155                 return back_link, back_string
156             return None, None
157         return None, None
158 
159     def has_valid_token_in_session(self, request):
160         """Return whether a valid token is stored in the session.
161 
162         The token is valid if it is valid for the respective module.
163         """
164         if "voting_tokens" in request.session:
165             module_key = str(self.module.id)
166             if module_key in request.session["voting_tokens"]:
167                 return (
168                     VotingToken.get_voting_token_by_hash(
169                         token_hash=request.session["voting_tokens"][module_key],
170                         module=self.module,
171                     )
172                     is not None
173                 )
174         return False
175 
176     def get_context_data(self, **kwargs):
177         context = super().get_context_data(**kwargs)
178         back_link, back_string = self.get_back()
179         context["back"] = back_link
180         context["back_string"] = back_string
181         context["has_valid_token_in_session"] = self.has_valid_token_in_session(
182             self.request
183         )
184         return context
185 
186 
187 class ProposalCreateView(idea_views.AbstractIdeaCreateView):
188     model = models.Proposal
189     form_class = forms.ProposalForm
190     permission_required = "meinberlin_budgeting.add_proposal"
191     template_name = "meinberlin_budgeting/proposal_create_form.html"
192 
193     def get_form_kwargs(self):
194         kwargs = super().get_form_kwargs()
195         kwargs["user"] = self.request.user
196         return kwargs
197 
198 
199 class ProposalUpdateView(idea_views.AbstractIdeaUpdateView):
200     model = models.Proposal
201     form_class = forms.ProposalForm
202     permission_required = "meinberlin_budgeting.change_proposal"
203     template_name = "meinberlin_budgeting/proposal_update_form.html"
204 
205     def get_form_kwargs(self):
206         kwargs = super().get_form_kwargs()
207         kwargs["user"] = self.request.user
208         return kwargs
209 
210 
211 class ProposalDeleteView(idea_views.AbstractIdeaDeleteView):
212     model = models.Proposal
213     success_message = _("Your budget request has been deleted")
214     permission_required = "meinberlin_budgeting.change_proposal"
215     template_name = "meinberlin_budgeting/proposal_confirm_delete.html"
216 
217 
218 class ProposalModerateView(idea_views.AbstractIdeaModerateView):
219     model = models.Proposal
220     permission_required = "meinberlin_budgeting.moderate_proposal"
221     template_name = "meinberlin_budgeting/proposal_moderate_form.html"
222     moderateable_form_class = forms.ProposalModerateForm
223     remark_form_class = ModeratorRemarkForm
224 
225 
226 class ProposalDashboardExportView(DashboardExportView):
227     template_name = "a4exports/export_dashboard.html"
228 
229     def get_context_data(self, **kwargs):
230         context = super().get_context_data(**kwargs)
231         context["export"] = reverse(
232             "a4dashboard:budgeting-export", kwargs={"module_slug": self.module.slug}
233         )
234         context["comment_export"] = reverse(
235             "a4dashboard:budgeting-comment-export",
236             kwargs={"module_slug": self.module.slug},
237         )
238         return context
239
```
--- 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/budgeting/views.py b/meinberlin/apps/budgeting/views.py
--- a/meinberlin/apps/budgeting/views.py
+++ b/meinberlin/apps/budgeting/views.py
@@ -140,21 +140,22 @@
         are remembered when going back, we check if the referer is a
         module or project detail view and add the appropriate back url.
         """
+        back_link = self.module.get_detail_url
+        back_string = _("map")
         if "Referer" in self.request.headers:
             referer = self.request.headers["Referer"]
             parsed_url = urlparse(referer)
             match = resolve(parsed_url.path)
             if match.url_name == "project-detail" or match.url_name == "module-detail":
                 back_mode = None
-                back_string = _("map")
                 if "mode" in parse_qs(parsed_url.query):
                     back_mode = parse_qs(parsed_url.query)["mode"][0]
                     if back_mode == "list":
                         back_string = _("list")
                 back_link = referer + "#proposal_{}".format(self.object.id)
                 return back_link, back_string
-            return None, None
-        return None, None
+            return back_link, back_string
+        return back_link, back_string
 
     def has_valid_token_in_session(self, request):
         """Return whether a valid token is stored in the session.

{"golden_diff": "diff --git a/meinberlin/apps/budgeting/views.py b/meinberlin/apps/budgeting/views.py\n--- a/meinberlin/apps/budgeting/views.py\n+++ b/meinberlin/apps/budgeting/views.py\n@@ -140,21 +140,22 @@\n         are remembered when going back, we check if the referer is a\n         module or project detail view and add the appropriate back url.\n         \"\"\"\n+        back_link = self.module.get_detail_url\n+        back_string = _(\"map\")\n         if \"Referer\" in self.request.headers:\n             referer = self.request.headers[\"Referer\"]\n             parsed_url = urlparse(referer)\n             match = resolve(parsed_url.path)\n             if match.url_name == \"project-detail\" or match.url_name == \"module-detail\":\n                 back_mode = None\n-                back_string = _(\"map\")\n                 if \"mode\" in parse_qs(parsed_url.query):\n                     back_mode = parse_qs(parsed_url.query)[\"mode\"][0]\n                     if back_mode == \"list\":\n                         back_string = _(\"list\")\n                 back_link = referer + \"#proposal_{}\".format(self.object.id)\n                 return back_link, back_string\n-            return None, None\n-        return None, None\n+            return back_link, back_string\n+        return back_link, back_string\n \n     def has_valid_token_in_session(self, request):\n         \"\"\"Return whether a valid token is stored in the session.\n", "issue": "Breadcrumb in modul \"Priorisierung mit Karte\" is saying always \"list\" \n**URL:** https://meinberlin-dev.liqd.net/maptopicprio/2022-00910/\r\n**user:** any\r\n**expected behaviour:** When coming from map I don't want to get confused by a button which says \"list\" even though you going back to the map.\r\n**behaviour:** In modul \"Priorisierung mit Karte\" in the detail view the breadcrumb says always list. When you for example come from the map, you go back to map but breadcrumb says \"list\".\r\n**important screensize:** -\r\n**device & browser:** mac ff\r\n**Comment/Question:** in the other moduls with ideas/proposals (except B\u00fcrger*innenhaushalt), it's saying \"Back\" (\"Zur\u00fcck\") and neither \"list\" nor \"map\". Probably related to this issue: https://github.com/liqd/a4-meinberlin/issues/4816\r\n\r\nScreenshot?\r\n\n", "before_files": [{"content": "from urllib.parse import parse_qs\nfrom urllib.parse import urlparse\n\nimport django_filters\nfrom django.urls import resolve\nfrom django.urls import reverse\nfrom django.utils.translation import gettext_lazy as _\n\nfrom adhocracy4.categories import filters as category_filters\nfrom adhocracy4.exports.views import DashboardExportView\nfrom adhocracy4.filters import filters as a4_filters\nfrom adhocracy4.labels import filters as label_filters\nfrom adhocracy4.modules.predicates import module_is_between_phases\nfrom adhocracy4.projects.mixins import DisplayProjectOrModuleMixin\nfrom meinberlin.apps.ideas import views as idea_views\nfrom meinberlin.apps.moderatorremark.forms import ModeratorRemarkForm\nfrom meinberlin.apps.projects.views import ArchivedWidget\nfrom meinberlin.apps.votes.forms import TokenForm\nfrom meinberlin.apps.votes.models import VotingToken\n\nfrom . import forms\nfrom . import models\n\n\ndef get_ordering_choices(view):\n    choices = ((\"-created\", _(\"Most recent\")),)\n    if view.module.has_feature(\"rate\", models.Proposal):\n        choices += ((\"-positive_rating_count\", _(\"Most popular\")),)\n    elif view.module.has_feature(\"support\", models.Proposal):\n        choices += ((\"-positive_rating_count\", _(\"Most support\")),)\n    choices += (\n        (\"-comment_count\", _(\"Most commented\")),\n        (\"dailyrandom\", _(\"Random\")),\n    )\n    return choices\n\n\ndef get_default_ordering(view):\n    if module_is_between_phases(\n        \"meinberlin_budgeting:support\", \"meinberlin_budgeting:voting\", view.module\n    ):\n        return \"-positive_rating_count\"\n    elif (\n        view.module.has_feature(\"vote\", models.Proposal)\n        and view.module.module_has_finished\n    ):\n        return \"-token_vote_count\"\n    return \"dailyrandom\"\n\n\nclass ProposalFilterSet(a4_filters.DefaultsFilterSet):\n    defaults = {\"is_archived\": \"false\"}\n    category = category_filters.CategoryFilter()\n    labels = label_filters.LabelFilter()\n    ordering = a4_filters.DistinctOrderingWithDailyRandomFilter(\n        choices=get_ordering_choices\n    )\n    is_archived = django_filters.BooleanFilter(widget=ArchivedWidget)\n\n    class Meta:\n        model = models.Proposal\n        fields = [\"category\", \"labels\", \"is_archived\"]\n\n    def __init__(self, data, *args, **kwargs):\n        self.defaults[\"ordering\"] = get_default_ordering(kwargs[\"view\"])\n        super().__init__(data, *args, **kwargs)\n\n\nclass ProposalListView(idea_views.AbstractIdeaListView, DisplayProjectOrModuleMixin):\n    model = models.Proposal\n    filter_set = ProposalFilterSet\n\n    def has_valid_token_in_session(self, request):\n        \"\"\"Return whether a valid token is stored in the session.\n\n        The token is valid if it is valid for the respective module.\n        \"\"\"\n        if \"voting_tokens\" in request.session:\n            module_key = str(self.module.id)\n            if module_key in request.session[\"voting_tokens\"]:\n                return (\n                    VotingToken.get_voting_token_by_hash(\n                        token_hash=request.session[\"voting_tokens\"][module_key],\n                        module=self.module,\n                    )\n                    is not None\n                )\n        return False\n\n    def dispatch(self, request, **kwargs):\n        self.mode = request.GET.get(\"mode\", \"map\")\n        if self.mode == \"map\":\n            self.paginate_by = 0\n        return super().dispatch(request, **kwargs)\n\n    def get_queryset(self):\n        return super().get_queryset().filter(module=self.module)\n\n    def get_context_data(self, **kwargs):\n        if \"token_form\" not in kwargs:\n            token_form = TokenForm(module_id=self.module.id)\n            kwargs[\"token_form\"] = token_form\n        kwargs[\"valid_token_present\"] = self.has_valid_token_in_session(self.request)\n        return super().get_context_data(**kwargs)\n\n    def post(self, request, *args, **kwargs):\n        self.object_list = self.get_queryset()\n        token_form = TokenForm(request.POST, module_id=self.module.id)\n        if token_form.is_valid():\n            if \"voting_tokens\" in request.session:\n                request.session[\"voting_tokens\"][\n                    str(self.module.id)\n                ] = token_form.cleaned_data[\"token\"]\n                request.session.save()\n            else:\n                request.session[\"voting_tokens\"] = {\n                    str(self.module.id): token_form.cleaned_data[\"token\"]\n                }\n            kwargs[\"valid_token_present\"] = True\n            self.mode = \"list\"\n        kwargs[\"token_form\"] = token_form\n        context = super().get_context_data(**kwargs)\n        return self.render_to_response(context)\n\n\nclass ProposalDetailView(idea_views.AbstractIdeaDetailView):\n    model = models.Proposal\n    queryset = (\n        models.Proposal.objects.annotate_positive_rating_count()\n        .annotate_negative_rating_count()\n        .annotate_token_vote_count()\n    )\n    permission_required = \"meinberlin_budgeting.view_proposal\"\n\n    def get_back(self):\n        \"\"\"\n        Get last page to return to if was project or module view.\n\n        To make sure all the filters and the display mode (map or list)\n        are remembered when going back, we check if the referer is a\n        module or project detail view and add the appropriate back url.\n        \"\"\"\n        if \"Referer\" in self.request.headers:\n            referer = self.request.headers[\"Referer\"]\n            parsed_url = urlparse(referer)\n            match = resolve(parsed_url.path)\n            if match.url_name == \"project-detail\" or match.url_name == \"module-detail\":\n                back_mode = None\n                back_string = _(\"map\")\n                if \"mode\" in parse_qs(parsed_url.query):\n                    back_mode = parse_qs(parsed_url.query)[\"mode\"][0]\n                    if back_mode == \"list\":\n                        back_string = _(\"list\")\n                back_link = referer + \"#proposal_{}\".format(self.object.id)\n                return back_link, back_string\n            return None, None\n        return None, None\n\n    def has_valid_token_in_session(self, request):\n        \"\"\"Return whether a valid token is stored in the session.\n\n        The token is valid if it is valid for the respective module.\n        \"\"\"\n        if \"voting_tokens\" in request.session:\n            module_key = str(self.module.id)\n            if module_key in request.session[\"voting_tokens\"]:\n                return (\n                    VotingToken.get_voting_token_by_hash(\n                        token_hash=request.session[\"voting_tokens\"][module_key],\n                        module=self.module,\n                    )\n                    is not None\n                )\n        return False\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        back_link, back_string = self.get_back()\n        context[\"back\"] = back_link\n        context[\"back_string\"] = back_string\n        context[\"has_valid_token_in_session\"] = self.has_valid_token_in_session(\n            self.request\n        )\n        return context\n\n\nclass ProposalCreateView(idea_views.AbstractIdeaCreateView):\n    model = models.Proposal\n    form_class = forms.ProposalForm\n    permission_required = \"meinberlin_budgeting.add_proposal\"\n    template_name = \"meinberlin_budgeting/proposal_create_form.html\"\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"user\"] = self.request.user\n        return kwargs\n\n\nclass ProposalUpdateView(idea_views.AbstractIdeaUpdateView):\n    model = models.Proposal\n    form_class = forms.ProposalForm\n    permission_required = \"meinberlin_budgeting.change_proposal\"\n    template_name = \"meinberlin_budgeting/proposal_update_form.html\"\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"user\"] = self.request.user\n        return kwargs\n\n\nclass ProposalDeleteView(idea_views.AbstractIdeaDeleteView):\n    model = models.Proposal\n    success_message = _(\"Your budget request has been deleted\")\n    permission_required = \"meinberlin_budgeting.change_proposal\"\n    template_name = \"meinberlin_budgeting/proposal_confirm_delete.html\"\n\n\nclass ProposalModerateView(idea_views.AbstractIdeaModerateView):\n    model = models.Proposal\n    permission_required = \"meinberlin_budgeting.moderate_proposal\"\n    template_name = \"meinberlin_budgeting/proposal_moderate_form.html\"\n    moderateable_form_class = forms.ProposalModerateForm\n    remark_form_class = ModeratorRemarkForm\n\n\nclass ProposalDashboardExportView(DashboardExportView):\n    template_name = \"a4exports/export_dashboard.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"export\"] = reverse(\n            \"a4dashboard:budgeting-export\", kwargs={\"module_slug\": self.module.slug}\n        )\n        context[\"comment_export\"] = reverse(\n            \"a4dashboard:budgeting-comment-export\",\n            kwargs={\"module_slug\": self.module.slug},\n        )\n        return context\n", "path": "meinberlin/apps/budgeting/views.py"}], "after_files": [{"content": "from urllib.parse import parse_qs\nfrom urllib.parse import urlparse\n\nimport django_filters\nfrom django.urls import resolve\nfrom django.urls import reverse\nfrom django.utils.translation import gettext_lazy as _\n\nfrom adhocracy4.categories import filters as category_filters\nfrom adhocracy4.exports.views import DashboardExportView\nfrom adhocracy4.filters import filters as a4_filters\nfrom adhocracy4.labels import filters as label_filters\nfrom adhocracy4.modules.predicates import module_is_between_phases\nfrom adhocracy4.projects.mixins import DisplayProjectOrModuleMixin\nfrom meinberlin.apps.ideas import views as idea_views\nfrom meinberlin.apps.moderatorremark.forms import ModeratorRemarkForm\nfrom meinberlin.apps.projects.views import ArchivedWidget\nfrom meinberlin.apps.votes.forms import TokenForm\nfrom meinberlin.apps.votes.models import VotingToken\n\nfrom . import forms\nfrom . import models\n\n\ndef get_ordering_choices(view):\n    choices = ((\"-created\", _(\"Most recent\")),)\n    if view.module.has_feature(\"rate\", models.Proposal):\n        choices += ((\"-positive_rating_count\", _(\"Most popular\")),)\n    elif view.module.has_feature(\"support\", models.Proposal):\n        choices += ((\"-positive_rating_count\", _(\"Most support\")),)\n    choices += (\n        (\"-comment_count\", _(\"Most commented\")),\n        (\"dailyrandom\", _(\"Random\")),\n    )\n    return choices\n\n\ndef get_default_ordering(view):\n    if module_is_between_phases(\n        \"meinberlin_budgeting:support\", \"meinberlin_budgeting:voting\", view.module\n    ):\n        return \"-positive_rating_count\"\n    elif (\n        view.module.has_feature(\"vote\", models.Proposal)\n        and view.module.module_has_finished\n    ):\n        return \"-token_vote_count\"\n    return \"dailyrandom\"\n\n\nclass ProposalFilterSet(a4_filters.DefaultsFilterSet):\n    defaults = {\"is_archived\": \"false\"}\n    category = category_filters.CategoryFilter()\n    labels = label_filters.LabelFilter()\n    ordering = a4_filters.DistinctOrderingWithDailyRandomFilter(\n        choices=get_ordering_choices\n    )\n    is_archived = django_filters.BooleanFilter(widget=ArchivedWidget)\n\n    class Meta:\n        model = models.Proposal\n        fields = [\"category\", \"labels\", \"is_archived\"]\n\n    def __init__(self, data, *args, **kwargs):\n        self.defaults[\"ordering\"] = get_default_ordering(kwargs[\"view\"])\n        super().__init__(data, *args, **kwargs)\n\n\nclass ProposalListView(idea_views.AbstractIdeaListView, DisplayProjectOrModuleMixin):\n    model = models.Proposal\n    filter_set = ProposalFilterSet\n\n    def has_valid_token_in_session(self, request):\n        \"\"\"Return whether a valid token is stored in the session.\n\n        The token is valid if it is valid for the respective module.\n        \"\"\"\n        if \"voting_tokens\" in request.session:\n            module_key = str(self.module.id)\n            if module_key in request.session[\"voting_tokens\"]:\n                return (\n                    VotingToken.get_voting_token_by_hash(\n                        token_hash=request.session[\"voting_tokens\"][module_key],\n                        module=self.module,\n                    )\n                    is not None\n                )\n        return False\n\n    def dispatch(self, request, **kwargs):\n        self.mode = request.GET.get(\"mode\", \"map\")\n        if self.mode == \"map\":\n            self.paginate_by = 0\n        return super().dispatch(request, **kwargs)\n\n    def get_queryset(self):\n        return super().get_queryset().filter(module=self.module)\n\n    def get_context_data(self, **kwargs):\n        if \"token_form\" not in kwargs:\n            token_form = TokenForm(module_id=self.module.id)\n            kwargs[\"token_form\"] = token_form\n        kwargs[\"valid_token_present\"] = self.has_valid_token_in_session(self.request)\n        return super().get_context_data(**kwargs)\n\n    def post(self, request, *args, **kwargs):\n        self.object_list = self.get_queryset()\n        token_form = TokenForm(request.POST, module_id=self.module.id)\n        if token_form.is_valid():\n            if \"voting_tokens\" in request.session:\n                request.session[\"voting_tokens\"][\n                    str(self.module.id)\n                ] = token_form.cleaned_data[\"token\"]\n                request.session.save()\n            else:\n                request.session[\"voting_tokens\"] = {\n                    str(self.module.id): token_form.cleaned_data[\"token\"]\n                }\n            kwargs[\"valid_token_present\"] = True\n            self.mode = \"list\"\n        kwargs[\"token_form\"] = token_form\n        context = super().get_context_data(**kwargs)\n        return self.render_to_response(context)\n\n\nclass ProposalDetailView(idea_views.AbstractIdeaDetailView):\n    model = models.Proposal\n    queryset = (\n        models.Proposal.objects.annotate_positive_rating_count()\n        .annotate_negative_rating_count()\n        .annotate_token_vote_count()\n    )\n    permission_required = \"meinberlin_budgeting.view_proposal\"\n\n    def get_back(self):\n        \"\"\"\n        Get last page to return to if was project or module view.\n\n        To make sure all the filters and the display mode (map or list)\n        are remembered when going back, we check if the referer is a\n        module or project detail view and add the appropriate back url.\n        \"\"\"\n        back_link = self.module.get_detail_url\n        back_string = _(\"map\")\n        if \"Referer\" in self.request.headers:\n            referer = self.request.headers[\"Referer\"]\n            parsed_url = urlparse(referer)\n            match = resolve(parsed_url.path)\n            if match.url_name == \"project-detail\" or match.url_name == \"module-detail\":\n                back_mode = None\n                if \"mode\" in parse_qs(parsed_url.query):\n                    back_mode = parse_qs(parsed_url.query)[\"mode\"][0]\n                    if back_mode == \"list\":\n                        back_string = _(\"list\")\n                back_link = referer + \"#proposal_{}\".format(self.object.id)\n                return back_link, back_string\n            return back_link, back_string\n        return back_link, back_string\n\n    def has_valid_token_in_session(self, request):\n        \"\"\"Return whether a valid token is stored in the session.\n\n        The token is valid if it is valid for the respective module.\n        \"\"\"\n        if \"voting_tokens\" in request.session:\n            module_key = str(self.module.id)\n            if module_key in request.session[\"voting_tokens\"]:\n                return (\n                    VotingToken.get_voting_token_by_hash(\n                        token_hash=request.session[\"voting_tokens\"][module_key],\n                        module=self.module,\n                    )\n                    is not None\n                )\n        return False\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        back_link, back_string = self.get_back()\n        context[\"back\"] = back_link\n        context[\"back_string\"] = back_string\n        context[\"has_valid_token_in_session\"] = self.has_valid_token_in_session(\n            self.request\n        )\n        return context\n\n\nclass ProposalCreateView(idea_views.AbstractIdeaCreateView):\n    model = models.Proposal\n    form_class = forms.ProposalForm\n    permission_required = \"meinberlin_budgeting.add_proposal\"\n    template_name = \"meinberlin_budgeting/proposal_create_form.html\"\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"user\"] = self.request.user\n        return kwargs\n\n\nclass ProposalUpdateView(idea_views.AbstractIdeaUpdateView):\n    model = models.Proposal\n    form_class = forms.ProposalForm\n    permission_required = \"meinberlin_budgeting.change_proposal\"\n    template_name = \"meinberlin_budgeting/proposal_update_form.html\"\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs[\"user\"] = self.request.user\n        return kwargs\n\n\nclass ProposalDeleteView(idea_views.AbstractIdeaDeleteView):\n    model = models.Proposal\n    success_message = _(\"Your budget request has been deleted\")\n    permission_required = \"meinberlin_budgeting.change_proposal\"\n    template_name = \"meinberlin_budgeting/proposal_confirm_delete.html\"\n\n\nclass ProposalModerateView(idea_views.AbstractIdeaModerateView):\n    model = models.Proposal\n    permission_required = \"meinberlin_budgeting.moderate_proposal\"\n    template_name = \"meinberlin_budgeting/proposal_moderate_form.html\"\n    moderateable_form_class = forms.ProposalModerateForm\n    remark_form_class = ModeratorRemarkForm\n\n\nclass ProposalDashboardExportView(DashboardExportView):\n    template_name = \"a4exports/export_dashboard.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"export\"] = reverse(\n            \"a4dashboard:budgeting-export\", kwargs={\"module_slug\": self.module.slug}\n        )\n        context[\"comment_export\"] = reverse(\n            \"a4dashboard:budgeting-comment-export\",\n            kwargs={\"module_slug\": self.module.slug},\n        )\n        return context\n", "path": "meinberlin/apps/budgeting/views.py"}]}