We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
breadcrumb navigation does not work properly
**URL:**https://meinberlin-dev.liqd.net/budgeting/2023-00998/
**user:** user with code
**expected behaviour:** breadcrumb navigation works properly
**behaviour:** project page, enter code above map, get redirected to list, vote on list, go into proposal detail -> breadbrumb is on "map". This does not happen when: project page, enter code above map, get redirected to list, go back to map, go back to list, vote on list, go into proposal detail
**important screensize:**
**device & browser:** tested firefox and safari
**Comment/Question:** 

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

{"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@@ -123,7 +123,6 @@\n                 datetime.datetime.now() + TOKEN_SESSION_EXPIRE\n             ).timestamp()\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", "issue": "breadcrumb navigation does not work properly\n**URL:**https://meinberlin-dev.liqd.net/budgeting/2023-00998/\r\n**user:** user with code\r\n**expected behaviour:** breadcrumb navigation works properly\r\n**behaviour:** project page, enter code above map, get redirected to list, vote on list, go into proposal detail -> breadbrumb is on \"map\". This does not happen when: project page, enter code above map, get redirected to list, go back to map, go back to list, vote on list, go into proposal detail\r\n**important screensize:**\r\n**device & browser:** tested firefox and safari\r\n**Comment/Question:** \r\n\r\nScreenshot?\r\n\n", "before_files": [{"content": "import datetime\nfrom 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\nTOKEN_SESSION_EXPIRE = datetime.timedelta(hours=12)\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.modified = True\n            else:\n                request.session[\"voting_tokens\"] = {\n                    str(self.module.id): token_form.cleaned_data[\"token\"]\n                }\n            request.session[\"token_expire_date\"] = (\n                datetime.datetime.now() + TOKEN_SESSION_EXPIRE\n            ).timestamp()\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                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"}], "after_files": [{"content": "import datetime\nfrom 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\nTOKEN_SESSION_EXPIRE = datetime.timedelta(hours=12)\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.modified = True\n            else:\n                request.session[\"voting_tokens\"] = {\n                    str(self.module.id): token_form.cleaned_data[\"token\"]\n                }\n            request.session[\"token_expire_date\"] = (\n                datetime.datetime.now() + TOKEN_SESSION_EXPIRE\n            ).timestamp()\n            kwargs[\"valid_token_present\"] = True\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                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"}]}