prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  testing 4295: 402 error for poll export
  **URL:** https://meinberlin-dev.liqd.net/dashboard/modules/umfrage-24/poll/export/
  **user:** initiator, moderator, group member
  **expected behaviour:** download export
  **behaviour:** 403 error
  **important screensize:**
  **device & browser:** big sur, firefox
  **Comment/Question:** 
  
  Screenshot?
  
  
  </issue>
  <code>
  [start of meinberlin/apps/polls/exports.py]
  1 from django.utils.translation import ugettext as _
  2 from rules.contrib.views import PermissionRequiredMixin
  3 
  4 from adhocracy4.comments.models import Comment
  5 from adhocracy4.exports import mixins
  6 from adhocracy4.exports import views as export_views
  7 from adhocracy4.polls import models as poll_models
  8 from meinberlin.apps.users.models import User
  9 
  10 
  11 class PollCommentExportView(
  12         PermissionRequiredMixin,
  13         mixins.ExportModelFieldsMixin,
  14         mixins.UserGeneratedContentExportMixin,
  15         mixins.ItemExportWithLinkMixin,
  16         mixins.CommentExportWithRepliesToMixin,
  17         export_views.BaseItemExportView
  18 ):
  19 
  20     model = Comment
  21 
  22     fields = ['id', 'comment', 'created']
  23     permission_required = 'a4projects.change_project'
  24 
  25     def get_permission_object(self):
  26         return self.module.project
  27 
  28     def get_queryset(self):
  29         comments = (
  30             Comment.objects.filter(poll__module=self.module) |
  31             Comment.objects.filter(parent_comment__poll__module=self.module)
  32         )
  33         return comments
  34 
  35     def get_virtual_fields(self, virtual):
  36         virtual.setdefault('id', _('ID'))
  37         virtual.setdefault('comment', _('Comment'))
  38         virtual.setdefault('created', _('Created'))
  39         return super().get_virtual_fields(virtual)
  40 
  41     @property
  42     def raise_exception(self):
  43         return self.request.user.is_authenticated
  44 
  45 
  46 class PollExportView(
  47     PermissionRequiredMixin,
  48     export_views.BaseItemExportView
  49 ):
  50 
  51     permission_required = 'a4projects.change_project'
  52 
  53     def get_queryset(self):
  54         creators_vote = poll_models.Vote.objects.filter(
  55             choice__question__poll=self.poll).values_list('creator', flat=True)
  56         creators_answer = poll_models.Answer.objects.filter(
  57             question__poll=self.poll).values_list('creator', flat=True)
  58         creator_ids = list(set(creators_vote).union(set(creators_answer)))
  59         return User.objects.filter(pk__in=creator_ids)
  60 
  61     @property
  62     def poll(self):
  63         return poll_models.Poll.objects.get(module=self.module)
  64 
  65     @property
  66     def single_choice_questions(self):
  67         return self.poll.questions.filter(
  68             multiple_choice=False,
  69             is_open=False).order_by('id')
  70 
  71     @property
  72     def multiple_choice_questions(self):
  73         return self.poll.questions.filter(multiple_choice=True).order_by('id')
  74 
  75     @property
  76     def open_questions(self):
  77         return self.poll.questions.filter(is_open=True).order_by('id')
  78 
  79     def get_virtual_fields(self, virtual):
  80         virtual = super().get_virtual_fields(virtual)
  81         virtual = self.get_virtual_fields_choice_questions(
  82             virtual, self.single_choice_questions)
  83         virtual = self.get_virtual_fields_choice_questions(
  84             virtual, self.multiple_choice_questions)
  85         virtual = self.get_virtual_fields_open_questions(
  86             virtual, self.open_questions)
  87 
  88         return virtual
  89 
  90     def get_virtual_fields_choice_questions(self, virtual, choice_questions):
  91         for question in choice_questions.all():
  92             for choice in question.choices.all():
  93                 identifier = 'Q' + str(question.pk) + '_A' + str(choice.pk)
  94                 virtual[(choice, False)] = identifier
  95                 if choice.is_other_choice:
  96                     identifier_answer = identifier + '_text'
  97                     virtual[(choice, True)] = identifier_answer
  98 
  99         return virtual
  100 
  101     def get_virtual_fields_open_questions(self, virtual, open_questions):
  102         for question in open_questions.all():
  103             identifier = 'Q' + str(question.pk)
  104             virtual[(question, False)] = identifier
  105             identifier_answer = identifier + '_text'
  106             virtual[(question, True)] = identifier_answer
  107 
  108         return virtual
  109 
  110     def get_field_data(self, user, field):
  111         field_object, is_text_field = field
  112 
  113         if type(field_object) == poll_models.Choice:
  114             votes_qs = poll_models.Vote.objects.filter(
  115                 choice=field_object,
  116                 creator=user)
  117             if not is_text_field:
  118                 value = int(votes_qs.exists())
  119             else:
  120                 vote = votes_qs.first()
  121                 if vote:
  122                     value = poll_models.OtherVote.objects.get(vote=vote).answer
  123                 else:
  124                     value = ''
  125         else:  # field_object is question
  126             answers_qs = poll_models.Answer.objects.filter(
  127                 question=field_object,
  128                 creator=user)
  129             if not is_text_field:
  130                 value = int(answers_qs.exists())
  131             else:
  132                 answer = answers_qs.first()
  133                 if answer:
  134                     value = answer.answer
  135                 else:
  136                     value = ''
  137 
  138         return value
  139
  [end of meinberlin/apps/polls/exports.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/meinberlin/apps/polls/exports.py b/meinberlin/apps/polls/exports.py
  --- a/meinberlin/apps/polls/exports.py
  +++ b/meinberlin/apps/polls/exports.py
  @@ -50,6 +50,9 @@
   
       permission_required = 'a4projects.change_project'
   
  +    def get_permission_object(self):
  +        return self.module.project
  +
       def get_queryset(self):
           creators_vote = poll_models.Vote.objects.filter(
               choice__question__poll=self.poll).values_list('creator', flat=True)
  @@ -63,47 +66,37 @@
           return poll_models.Poll.objects.get(module=self.module)
   
       @property
  -    def single_choice_questions(self):
  -        return self.poll.questions.filter(
  -            multiple_choice=False,
  -            is_open=False).order_by('id')
  -
  -    @property
  -    def multiple_choice_questions(self):
  -        return self.poll.questions.filter(multiple_choice=True).order_by('id')
  -
  -    @property
  -    def open_questions(self):
  -        return self.poll.questions.filter(is_open=True).order_by('id')
  +    def questions(self):
  +        return self.poll.questions.all()
   
       def get_virtual_fields(self, virtual):
           virtual = super().get_virtual_fields(virtual)
  -        virtual = self.get_virtual_fields_choice_questions(
  -            virtual, self.single_choice_questions)
  -        virtual = self.get_virtual_fields_choice_questions(
  -            virtual, self.multiple_choice_questions)
  -        virtual = self.get_virtual_fields_open_questions(
  -            virtual, self.open_questions)
  +
  +        for question in self.questions:
  +            if question.is_open:
  +                virtual = \
  +                    self.get_virtual_field_open_question(virtual, question)
  +            else:
  +                virtual = \
  +                    self.get_virtual_field_choice_question(virtual, question)
   
           return virtual
   
  -    def get_virtual_fields_choice_questions(self, virtual, choice_questions):
  -        for question in choice_questions.all():
  -            for choice in question.choices.all():
  -                identifier = 'Q' + str(question.pk) + '_A' + str(choice.pk)
  -                virtual[(choice, False)] = identifier
  -                if choice.is_other_choice:
  -                    identifier_answer = identifier + '_text'
  -                    virtual[(choice, True)] = identifier_answer
  +    def get_virtual_field_choice_question(self, virtual, choice_question):
  +        for choice in choice_question.choices.all():
  +            identifier = 'Q' + str(choice_question.pk) + '_A' + str(choice.pk)
  +            virtual[(choice, False)] = identifier
  +            if choice.is_other_choice:
  +                identifier_answer = identifier + '_text'
  +                virtual[(choice, True)] = identifier_answer
   
           return virtual
   
  -    def get_virtual_fields_open_questions(self, virtual, open_questions):
  -        for question in open_questions.all():
  -            identifier = 'Q' + str(question.pk)
  -            virtual[(question, False)] = identifier
  -            identifier_answer = identifier + '_text'
  -            virtual[(question, True)] = identifier_answer
  +    def get_virtual_field_open_question(self, virtual, open_question):
  +        identifier = 'Q' + str(open_question.pk)
  +        virtual[(open_question, False)] = identifier
  +        identifier_answer = identifier + '_text'
  +        virtual[(open_question, True)] = identifier_answer
   
           return virtual
  
verification_info: {"golden_diff": "diff --git a/meinberlin/apps/polls/exports.py b/meinberlin/apps/polls/exports.py\n--- a/meinberlin/apps/polls/exports.py\n+++ b/meinberlin/apps/polls/exports.py\n@@ -50,6 +50,9 @@\n \n     permission_required = 'a4projects.change_project'\n \n+    def get_permission_object(self):\n+        return self.module.project\n+\n     def get_queryset(self):\n         creators_vote = poll_models.Vote.objects.filter(\n             choice__question__poll=self.poll).values_list('creator', flat=True)\n@@ -63,47 +66,37 @@\n         return poll_models.Poll.objects.get(module=self.module)\n \n     @property\n-    def single_choice_questions(self):\n-        return self.poll.questions.filter(\n-            multiple_choice=False,\n-            is_open=False).order_by('id')\n-\n-    @property\n-    def multiple_choice_questions(self):\n-        return self.poll.questions.filter(multiple_choice=True).order_by('id')\n-\n-    @property\n-    def open_questions(self):\n-        return self.poll.questions.filter(is_open=True).order_by('id')\n+    def questions(self):\n+        return self.poll.questions.all()\n \n     def get_virtual_fields(self, virtual):\n         virtual = super().get_virtual_fields(virtual)\n-        virtual = self.get_virtual_fields_choice_questions(\n-            virtual, self.single_choice_questions)\n-        virtual = self.get_virtual_fields_choice_questions(\n-            virtual, self.multiple_choice_questions)\n-        virtual = self.get_virtual_fields_open_questions(\n-            virtual, self.open_questions)\n+\n+        for question in self.questions:\n+            if question.is_open:\n+                virtual = \\\n+                    self.get_virtual_field_open_question(virtual, question)\n+            else:\n+                virtual = \\\n+                    self.get_virtual_field_choice_question(virtual, question)\n \n         return virtual\n \n-    def get_virtual_fields_choice_questions(self, virtual, choice_questions):\n-        for question in choice_questions.all():\n-            for choice in question.choices.all():\n-                identifier = 'Q' + str(question.pk) + '_A' + str(choice.pk)\n-                virtual[(choice, False)] = identifier\n-                if choice.is_other_choice:\n-                    identifier_answer = identifier + '_text'\n-                    virtual[(choice, True)] = identifier_answer\n+    def get_virtual_field_choice_question(self, virtual, choice_question):\n+        for choice in choice_question.choices.all():\n+            identifier = 'Q' + str(choice_question.pk) + '_A' + str(choice.pk)\n+            virtual[(choice, False)] = identifier\n+            if choice.is_other_choice:\n+                identifier_answer = identifier + '_text'\n+                virtual[(choice, True)] = identifier_answer\n \n         return virtual\n \n-    def get_virtual_fields_open_questions(self, virtual, open_questions):\n-        for question in open_questions.all():\n-            identifier = 'Q' + str(question.pk)\n-            virtual[(question, False)] = identifier\n-            identifier_answer = identifier + '_text'\n-            virtual[(question, True)] = identifier_answer\n+    def get_virtual_field_open_question(self, virtual, open_question):\n+        identifier = 'Q' + str(open_question.pk)\n+        virtual[(open_question, False)] = identifier\n+        identifier_answer = identifier + '_text'\n+        virtual[(open_question, True)] = identifier_answer\n \n         return virtual\n", "issue": "testing 4295: 402 error for poll export\n**URL:** https://meinberlin-dev.liqd.net/dashboard/modules/umfrage-24/poll/export/\r\n**user:** initiator, moderator, group member\r\n**expected behaviour:** download export\r\n**behaviour:** 403 error\r\n**important screensize:**\r\n**device & browser:** big sur, firefox\r\n**Comment/Question:** \r\n\r\nScreenshot?\r\n\n", "before_files": [{"content": "from django.utils.translation import ugettext as _\nfrom rules.contrib.views import PermissionRequiredMixin\n\nfrom adhocracy4.comments.models import Comment\nfrom adhocracy4.exports import mixins\nfrom adhocracy4.exports import views as export_views\nfrom adhocracy4.polls import models as poll_models\nfrom meinberlin.apps.users.models import User\n\n\nclass PollCommentExportView(\n        PermissionRequiredMixin,\n        mixins.ExportModelFieldsMixin,\n        mixins.UserGeneratedContentExportMixin,\n        mixins.ItemExportWithLinkMixin,\n        mixins.CommentExportWithRepliesToMixin,\n        export_views.BaseItemExportView\n):\n\n    model = Comment\n\n    fields = ['id', 'comment', 'created']\n    permission_required = 'a4projects.change_project'\n\n    def get_permission_object(self):\n        return self.module.project\n\n    def get_queryset(self):\n        comments = (\n            Comment.objects.filter(poll__module=self.module) |\n            Comment.objects.filter(parent_comment__poll__module=self.module)\n        )\n        return comments\n\n    def get_virtual_fields(self, virtual):\n        virtual.setdefault('id', _('ID'))\n        virtual.setdefault('comment', _('Comment'))\n        virtual.setdefault('created', _('Created'))\n        return super().get_virtual_fields(virtual)\n\n    @property\n    def raise_exception(self):\n        return self.request.user.is_authenticated\n\n\nclass PollExportView(\n    PermissionRequiredMixin,\n    export_views.BaseItemExportView\n):\n\n    permission_required = 'a4projects.change_project'\n\n    def get_queryset(self):\n        creators_vote = poll_models.Vote.objects.filter(\n            choice__question__poll=self.poll).values_list('creator', flat=True)\n        creators_answer = poll_models.Answer.objects.filter(\n            question__poll=self.poll).values_list('creator', flat=True)\n        creator_ids = list(set(creators_vote).union(set(creators_answer)))\n        return User.objects.filter(pk__in=creator_ids)\n\n    @property\n    def poll(self):\n        return poll_models.Poll.objects.get(module=self.module)\n\n    @property\n    def single_choice_questions(self):\n        return self.poll.questions.filter(\n            multiple_choice=False,\n            is_open=False).order_by('id')\n\n    @property\n    def multiple_choice_questions(self):\n        return self.poll.questions.filter(multiple_choice=True).order_by('id')\n\n    @property\n    def open_questions(self):\n        return self.poll.questions.filter(is_open=True).order_by('id')\n\n    def get_virtual_fields(self, virtual):\n        virtual = super().get_virtual_fields(virtual)\n        virtual = self.get_virtual_fields_choice_questions(\n            virtual, self.single_choice_questions)\n        virtual = self.get_virtual_fields_choice_questions(\n            virtual, self.multiple_choice_questions)\n        virtual = self.get_virtual_fields_open_questions(\n            virtual, self.open_questions)\n\n        return virtual\n\n    def get_virtual_fields_choice_questions(self, virtual, choice_questions):\n        for question in choice_questions.all():\n            for choice in question.choices.all():\n                identifier = 'Q' + str(question.pk) + '_A' + str(choice.pk)\n                virtual[(choice, False)] = identifier\n                if choice.is_other_choice:\n                    identifier_answer = identifier + '_text'\n                    virtual[(choice, True)] = identifier_answer\n\n        return virtual\n\n    def get_virtual_fields_open_questions(self, virtual, open_questions):\n        for question in open_questions.all():\n            identifier = 'Q' + str(question.pk)\n            virtual[(question, False)] = identifier\n            identifier_answer = identifier + '_text'\n            virtual[(question, True)] = identifier_answer\n\n        return virtual\n\n    def get_field_data(self, user, field):\n        field_object, is_text_field = field\n\n        if type(field_object) == poll_models.Choice:\n            votes_qs = poll_models.Vote.objects.filter(\n                choice=field_object,\n                creator=user)\n            if not is_text_field:\n                value = int(votes_qs.exists())\n            else:\n                vote = votes_qs.first()\n                if vote:\n                    value = poll_models.OtherVote.objects.get(vote=vote).answer\n                else:\n                    value = ''\n        else:  # field_object is question\n            answers_qs = poll_models.Answer.objects.filter(\n                question=field_object,\n                creator=user)\n            if not is_text_field:\n                value = int(answers_qs.exists())\n            else:\n                answer = answers_qs.first()\n                if answer:\n                    value = answer.answer\n                else:\n                    value = ''\n\n        return value\n", "path": "meinberlin/apps/polls/exports.py"}]}