We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Regression: File question required when editing ticket
This is the same issue as #1408, I'm not quite sure whether this should be a new bug because it's a regression or if the old bug should be reopened?

Long story short: We noticed in Pretix 4.3 that customers editing their order will be faced with file questions being `required` even though they have uploaded a file for that question already. The requirement comes from the `input` being marked as `required` and the browsers refusing to submit the form without something in there.

This was fixed in #1443, but it seems this doesn't work anymore. I haven't had time to look into this more, so I don't have a clue where it might fail.
Regression: File question required when editing ticket
This is the same issue as #1408, I'm not quite sure whether this should be a new bug because it's a regression or if the old bug should be reopened?

Long story short: We noticed in Pretix 4.3 that customers editing their order will be faced with file questions being `required` even though they have uploaded a file for that question already. The requirement comes from the `input` being marked as `required` and the browsers refusing to submit the form without something in there.

This was fixed in #1443, but it seems this doesn't work anymore. I haven't had time to look into this more, so I don't have a clue where it might fail.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/pretix/base/forms/widgets.py`
Content:
```
1 #
2 # This file is part of pretix (Community Edition).
3 #
4 # Copyright (C) 2014-2020 Raphael Michel and contributors
5 # Copyright (C) 2020-2021 rami.io GmbH and contributors
6 #
7 # This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
8 # Public License as published by the Free Software Foundation in version 3 of the License.
9 #
10 # ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
11 # applicable granting you additional permissions and placing additional restrictions on your usage of this software.
12 # Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
13 # this file, see <https://pretix.eu/about/en/license>.
14 #
15 # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17 # details.
18 #
19 # You should have received a copy of the GNU Affero General Public License along with this program.  If not, see
20 # <https://www.gnu.org/licenses/>.
21 #
22 
23 # This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of
24 # the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.
25 #
26 # This file may have since been changed and any changes are released under the terms of AGPLv3 as described above. A
27 # full history of changes and contributors is available at <https://github.com/pretix/pretix>.
28 #
29 # This file contains Apache-licensed contributions copyrighted by: Felix Schäfer
30 #
31 # Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is
32 # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
33 # License for the specific language governing permissions and limitations under the License.
34 
35 import os
36 from datetime import date
37 
38 from django import forms
39 from django.utils.formats import get_format
40 from django.utils.functional import lazy
41 from django.utils.timezone import get_current_timezone, now
42 from django.utils.translation import gettext_lazy as _
43 
44 
45 class DatePickerWidget(forms.DateInput):
46     def __init__(self, attrs=None, date_format=None):
47         attrs = attrs or {}
48         if 'placeholder' in attrs:
49             del attrs['placeholder']
50         date_attrs = dict(attrs)
51         date_attrs.setdefault('class', 'form-control')
52         date_attrs['class'] += ' datepickerfield'
53         date_attrs['autocomplete'] = 'off'
54 
55         def placeholder():
56             df = date_format or get_format('DATE_INPUT_FORMATS')[0]
57             return now().replace(
58                 year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0
59             ).strftime(df)
60 
61         date_attrs['placeholder'] = lazy(placeholder, str)
62 
63         forms.DateInput.__init__(self, date_attrs, date_format)
64 
65 
66 class TimePickerWidget(forms.TimeInput):
67     def __init__(self, attrs=None, time_format=None):
68         attrs = attrs or {}
69         if 'placeholder' in attrs:
70             del attrs['placeholder']
71         time_attrs = dict(attrs)
72         time_attrs.setdefault('class', 'form-control')
73         time_attrs['class'] += ' timepickerfield'
74         time_attrs['autocomplete'] = 'off'
75 
76         def placeholder():
77             tf = time_format or get_format('TIME_INPUT_FORMATS')[0]
78             return now().replace(
79                 year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0
80             ).strftime(tf)
81 
82         time_attrs['placeholder'] = lazy(placeholder, str)
83 
84         forms.TimeInput.__init__(self, time_attrs, time_format)
85 
86 
87 class UploadedFileWidget(forms.ClearableFileInput):
88     def __init__(self, *args, **kwargs):
89         # Browsers can't recognize that the server already has a file uploaded
90         # Don't mark this input as being required if we already have an answer
91         # (this needs to be done via the attrs, otherwise we wouldn't get the "required" star on the field label)
92         attrs = kwargs.get('attrs', {})
93         if kwargs.get('required') and kwargs.get('initial'):
94             attrs.update({'required': None})
95         kwargs.update({'attrs': attrs})
96 
97         self.position = kwargs.pop('position')
98         self.event = kwargs.pop('event')
99         self.answer = kwargs.pop('answer')
100         super().__init__(*args, **kwargs)
101 
102     class FakeFile:
103         def __init__(self, file, position, event, answer):
104             self.file = file
105             self.position = position
106             self.event = event
107             self.answer = answer
108 
109         def __str__(self):
110             return os.path.basename(self.file.name).split('.', 1)[-1]
111 
112         @property
113         def url(self):
114             from pretix.base.models import OrderPosition
115             from pretix.multidomain.urlreverse import eventreverse
116 
117             if isinstance(self.position, OrderPosition):
118                 return eventreverse(self.event, 'presale:event.order.download.answer', kwargs={
119                     'order': self.position.order.code,
120                     'secret': self.position.order.secret,
121                     'answer': self.answer.pk,
122                 })
123             else:
124                 return eventreverse(self.event, 'presale:event.cart.download.answer', kwargs={
125                     'answer': self.answer.pk,
126                 })
127 
128     def format_value(self, value):
129         if self.is_initial(value):
130             return self.FakeFile(value, self.position, self.event, self.answer)
131 
132 
133 class SplitDateTimePickerWidget(forms.SplitDateTimeWidget):
134     template_name = 'pretixbase/forms/widgets/splitdatetime.html'
135 
136     def __init__(self, attrs=None, date_format=None, time_format=None, min_date=None, max_date=None):
137         attrs = attrs or {}
138         if 'placeholder' in attrs:
139             del attrs['placeholder']
140         date_attrs = dict(attrs)
141         time_attrs = dict(attrs)
142         date_attrs.setdefault('class', 'form-control splitdatetimepart')
143         time_attrs.setdefault('class', 'form-control splitdatetimepart')
144         date_attrs.setdefault('autocomplete', 'off')
145         time_attrs.setdefault('autocomplete', 'off')
146         date_attrs['class'] += ' datepickerfield'
147         time_attrs['class'] += ' timepickerfield'
148         date_attrs['autocomplete'] = 'off'
149         time_attrs['autocomplete'] = 'off'
150         if min_date:
151             date_attrs['data-min'] = (
152                 min_date if isinstance(min_date, date) else min_date.astimezone(get_current_timezone()).date()
153             ).isoformat()
154         if max_date:
155             date_attrs['data-max'] = (
156                 max_date if isinstance(max_date, date) else max_date.astimezone(get_current_timezone()).date()
157             ).isoformat()
158 
159         def date_placeholder():
160             df = date_format or get_format('DATE_INPUT_FORMATS')[0]
161             return now().replace(
162                 year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0
163             ).strftime(df)
164 
165         def time_placeholder():
166             tf = time_format or get_format('TIME_INPUT_FORMATS')[0]
167             return now().replace(
168                 year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0
169             ).strftime(tf)
170 
171         date_attrs['placeholder'] = lazy(date_placeholder, str)
172         time_attrs['placeholder'] = lazy(time_placeholder, str)
173 
174         widgets = (
175             forms.DateInput(attrs=date_attrs, format=date_format),
176             forms.TimeInput(attrs=time_attrs, format=time_format),
177         )
178         # Skip one hierarchy level
179         forms.MultiWidget.__init__(self, widgets, attrs)
180 
181 
182 class BusinessBooleanRadio(forms.RadioSelect):
183     def __init__(self, require_business=False, attrs=None):
184         self.require_business = require_business
185         if self.require_business:
186             choices = (
187                 ('business', _('Business or institutional customer')),
188             )
189         else:
190             choices = (
191                 ('individual', _('Individual customer')),
192                 ('business', _('Business or institutional customer')),
193             )
194         super().__init__(attrs, choices)
195 
196     def format_value(self, value):
197         if self.require_business:
198             return 'business'
199         try:
200             return {True: 'business', False: 'individual'}[value]
201         except KeyError:
202             return 'individual'
203 
204     def value_from_datadict(self, data, files, name):
205         value = data.get(name)
206         if self.require_business:
207             return True
208         return {
209             'business': True,
210             True: True,
211             'True': True,
212             'individual': False,
213             'False': False,
214             False: False,
215         }.get(value)
216
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/pretix/base/forms/widgets.py b/src/pretix/base/forms/widgets.py
--- a/src/pretix/base/forms/widgets.py
+++ b/src/pretix/base/forms/widgets.py
@@ -86,14 +86,6 @@
 
 class UploadedFileWidget(forms.ClearableFileInput):
     def __init__(self, *args, **kwargs):
-        # Browsers can't recognize that the server already has a file uploaded
-        # Don't mark this input as being required if we already have an answer
-        # (this needs to be done via the attrs, otherwise we wouldn't get the "required" star on the field label)
-        attrs = kwargs.get('attrs', {})
-        if kwargs.get('required') and kwargs.get('initial'):
-            attrs.update({'required': None})
-        kwargs.update({'attrs': attrs})
-
         self.position = kwargs.pop('position')
         self.event = kwargs.pop('event')
         self.answer = kwargs.pop('answer')
@@ -125,6 +117,15 @@
                     'answer': self.answer.pk,
                 })
 
+    def get_context(self, name, value, attrs):
+        # Browsers can't recognize that the server already has a file uploaded
+        # Don't mark this input as being required if we already have an answer
+        # (this needs to be done via the attrs, otherwise we wouldn't get the "required" star on the field label)
+        ctx = super().get_context(name, value, attrs)
+        if ctx['widget']['is_initial']:
+            ctx['widget']['attrs']['required'] = False
+        return ctx
+
     def format_value(self, value):
         if self.is_initial(value):
             return self.FakeFile(value, self.position, self.event, self.answer)

{"golden_diff": "diff --git a/src/pretix/base/forms/widgets.py b/src/pretix/base/forms/widgets.py\n--- a/src/pretix/base/forms/widgets.py\n+++ b/src/pretix/base/forms/widgets.py\n@@ -86,14 +86,6 @@\n \n class UploadedFileWidget(forms.ClearableFileInput):\n     def __init__(self, *args, **kwargs):\n-        # Browsers can't recognize that the server already has a file uploaded\n-        # Don't mark this input as being required if we already have an answer\n-        # (this needs to be done via the attrs, otherwise we wouldn't get the \"required\" star on the field label)\n-        attrs = kwargs.get('attrs', {})\n-        if kwargs.get('required') and kwargs.get('initial'):\n-            attrs.update({'required': None})\n-        kwargs.update({'attrs': attrs})\n-\n         self.position = kwargs.pop('position')\n         self.event = kwargs.pop('event')\n         self.answer = kwargs.pop('answer')\n@@ -125,6 +117,15 @@\n                     'answer': self.answer.pk,\n                 })\n \n+    def get_context(self, name, value, attrs):\n+        # Browsers can't recognize that the server already has a file uploaded\n+        # Don't mark this input as being required if we already have an answer\n+        # (this needs to be done via the attrs, otherwise we wouldn't get the \"required\" star on the field label)\n+        ctx = super().get_context(name, value, attrs)\n+        if ctx['widget']['is_initial']:\n+            ctx['widget']['attrs']['required'] = False\n+        return ctx\n+\n     def format_value(self, value):\n         if self.is_initial(value):\n             return self.FakeFile(value, self.position, self.event, self.answer)\n", "issue": "Regression: File question required when editing ticket\nThis is the same issue as #1408, I'm not quite sure whether this should be a new bug because it's a regression or if the old bug should be reopened?\r\n\r\nLong story short: We noticed in Pretix 4.3 that customers editing their order will be faced with file questions being `required` even though they have uploaded a file for that question already. The requirement comes from the `input` being marked as `required` and the browsers refusing to submit the form without something in there.\r\n\r\nThis was fixed in #1443, but it seems this doesn't work anymore. I haven't had time to look into this more, so I don't have a clue where it might fail.\nRegression: File question required when editing ticket\nThis is the same issue as #1408, I'm not quite sure whether this should be a new bug because it's a regression or if the old bug should be reopened?\r\n\r\nLong story short: We noticed in Pretix 4.3 that customers editing their order will be faced with file questions being `required` even though they have uploaded a file for that question already. The requirement comes from the `input` being marked as `required` and the browsers refusing to submit the form without something in there.\r\n\r\nThis was fixed in #1443, but it seems this doesn't work anymore. I haven't had time to look into this more, so I don't have a clue where it might fail.\n", "before_files": [{"content": "#\n# This file is part of pretix (Community Edition).\n#\n# Copyright (C) 2014-2020 Raphael Michel and contributors\n# Copyright (C) 2020-2021 rami.io GmbH and contributors\n#\n# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General\n# Public License as published by the Free Software Foundation in version 3 of the License.\n#\n# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are\n# applicable granting you additional permissions and placing additional restrictions on your usage of this software.\n# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive\n# this file, see <https://pretix.eu/about/en/license>.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied\n# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more\n# details.\n#\n# You should have received a copy of the GNU Affero General Public License along with this program.  If not, see\n# <https://www.gnu.org/licenses/>.\n#\n\n# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of\n# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.\n#\n# This file may have since been changed and any changes are released under the terms of AGPLv3 as described above. A\n# full history of changes and contributors is available at <https://github.com/pretix/pretix>.\n#\n# This file contains Apache-licensed contributions copyrighted by: Felix Sch\u00e4fer\n#\n# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations under the License.\n\nimport os\nfrom datetime import date\n\nfrom django import forms\nfrom django.utils.formats import get_format\nfrom django.utils.functional import lazy\nfrom django.utils.timezone import get_current_timezone, now\nfrom django.utils.translation import gettext_lazy as _\n\n\nclass DatePickerWidget(forms.DateInput):\n    def __init__(self, attrs=None, date_format=None):\n        attrs = attrs or {}\n        if 'placeholder' in attrs:\n            del attrs['placeholder']\n        date_attrs = dict(attrs)\n        date_attrs.setdefault('class', 'form-control')\n        date_attrs['class'] += ' datepickerfield'\n        date_attrs['autocomplete'] = 'off'\n\n        def placeholder():\n            df = date_format or get_format('DATE_INPUT_FORMATS')[0]\n            return now().replace(\n                year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0\n            ).strftime(df)\n\n        date_attrs['placeholder'] = lazy(placeholder, str)\n\n        forms.DateInput.__init__(self, date_attrs, date_format)\n\n\nclass TimePickerWidget(forms.TimeInput):\n    def __init__(self, attrs=None, time_format=None):\n        attrs = attrs or {}\n        if 'placeholder' in attrs:\n            del attrs['placeholder']\n        time_attrs = dict(attrs)\n        time_attrs.setdefault('class', 'form-control')\n        time_attrs['class'] += ' timepickerfield'\n        time_attrs['autocomplete'] = 'off'\n\n        def placeholder():\n            tf = time_format or get_format('TIME_INPUT_FORMATS')[0]\n            return now().replace(\n                year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0\n            ).strftime(tf)\n\n        time_attrs['placeholder'] = lazy(placeholder, str)\n\n        forms.TimeInput.__init__(self, time_attrs, time_format)\n\n\nclass UploadedFileWidget(forms.ClearableFileInput):\n    def __init__(self, *args, **kwargs):\n        # Browsers can't recognize that the server already has a file uploaded\n        # Don't mark this input as being required if we already have an answer\n        # (this needs to be done via the attrs, otherwise we wouldn't get the \"required\" star on the field label)\n        attrs = kwargs.get('attrs', {})\n        if kwargs.get('required') and kwargs.get('initial'):\n            attrs.update({'required': None})\n        kwargs.update({'attrs': attrs})\n\n        self.position = kwargs.pop('position')\n        self.event = kwargs.pop('event')\n        self.answer = kwargs.pop('answer')\n        super().__init__(*args, **kwargs)\n\n    class FakeFile:\n        def __init__(self, file, position, event, answer):\n            self.file = file\n            self.position = position\n            self.event = event\n            self.answer = answer\n\n        def __str__(self):\n            return os.path.basename(self.file.name).split('.', 1)[-1]\n\n        @property\n        def url(self):\n            from pretix.base.models import OrderPosition\n            from pretix.multidomain.urlreverse import eventreverse\n\n            if isinstance(self.position, OrderPosition):\n                return eventreverse(self.event, 'presale:event.order.download.answer', kwargs={\n                    'order': self.position.order.code,\n                    'secret': self.position.order.secret,\n                    'answer': self.answer.pk,\n                })\n            else:\n                return eventreverse(self.event, 'presale:event.cart.download.answer', kwargs={\n                    'answer': self.answer.pk,\n                })\n\n    def format_value(self, value):\n        if self.is_initial(value):\n            return self.FakeFile(value, self.position, self.event, self.answer)\n\n\nclass SplitDateTimePickerWidget(forms.SplitDateTimeWidget):\n    template_name = 'pretixbase/forms/widgets/splitdatetime.html'\n\n    def __init__(self, attrs=None, date_format=None, time_format=None, min_date=None, max_date=None):\n        attrs = attrs or {}\n        if 'placeholder' in attrs:\n            del attrs['placeholder']\n        date_attrs = dict(attrs)\n        time_attrs = dict(attrs)\n        date_attrs.setdefault('class', 'form-control splitdatetimepart')\n        time_attrs.setdefault('class', 'form-control splitdatetimepart')\n        date_attrs.setdefault('autocomplete', 'off')\n        time_attrs.setdefault('autocomplete', 'off')\n        date_attrs['class'] += ' datepickerfield'\n        time_attrs['class'] += ' timepickerfield'\n        date_attrs['autocomplete'] = 'off'\n        time_attrs['autocomplete'] = 'off'\n        if min_date:\n            date_attrs['data-min'] = (\n                min_date if isinstance(min_date, date) else min_date.astimezone(get_current_timezone()).date()\n            ).isoformat()\n        if max_date:\n            date_attrs['data-max'] = (\n                max_date if isinstance(max_date, date) else max_date.astimezone(get_current_timezone()).date()\n            ).isoformat()\n\n        def date_placeholder():\n            df = date_format or get_format('DATE_INPUT_FORMATS')[0]\n            return now().replace(\n                year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0\n            ).strftime(df)\n\n        def time_placeholder():\n            tf = time_format or get_format('TIME_INPUT_FORMATS')[0]\n            return now().replace(\n                year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0\n            ).strftime(tf)\n\n        date_attrs['placeholder'] = lazy(date_placeholder, str)\n        time_attrs['placeholder'] = lazy(time_placeholder, str)\n\n        widgets = (\n            forms.DateInput(attrs=date_attrs, format=date_format),\n            forms.TimeInput(attrs=time_attrs, format=time_format),\n        )\n        # Skip one hierarchy level\n        forms.MultiWidget.__init__(self, widgets, attrs)\n\n\nclass BusinessBooleanRadio(forms.RadioSelect):\n    def __init__(self, require_business=False, attrs=None):\n        self.require_business = require_business\n        if self.require_business:\n            choices = (\n                ('business', _('Business or institutional customer')),\n            )\n        else:\n            choices = (\n                ('individual', _('Individual customer')),\n                ('business', _('Business or institutional customer')),\n            )\n        super().__init__(attrs, choices)\n\n    def format_value(self, value):\n        if self.require_business:\n            return 'business'\n        try:\n            return {True: 'business', False: 'individual'}[value]\n        except KeyError:\n            return 'individual'\n\n    def value_from_datadict(self, data, files, name):\n        value = data.get(name)\n        if self.require_business:\n            return True\n        return {\n            'business': True,\n            True: True,\n            'True': True,\n            'individual': False,\n            'False': False,\n            False: False,\n        }.get(value)\n", "path": "src/pretix/base/forms/widgets.py"}], "after_files": [{"content": "#\n# This file is part of pretix (Community Edition).\n#\n# Copyright (C) 2014-2020 Raphael Michel and contributors\n# Copyright (C) 2020-2021 rami.io GmbH and contributors\n#\n# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General\n# Public License as published by the Free Software Foundation in version 3 of the License.\n#\n# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are\n# applicable granting you additional permissions and placing additional restrictions on your usage of this software.\n# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive\n# this file, see <https://pretix.eu/about/en/license>.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied\n# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more\n# details.\n#\n# You should have received a copy of the GNU Affero General Public License along with this program.  If not, see\n# <https://www.gnu.org/licenses/>.\n#\n\n# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of\n# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.\n#\n# This file may have since been changed and any changes are released under the terms of AGPLv3 as described above. A\n# full history of changes and contributors is available at <https://github.com/pretix/pretix>.\n#\n# This file contains Apache-licensed contributions copyrighted by: Felix Sch\u00e4fer\n#\n# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations under the License.\n\nimport os\nfrom datetime import date\n\nfrom django import forms\nfrom django.utils.formats import get_format\nfrom django.utils.functional import lazy\nfrom django.utils.timezone import get_current_timezone, now\nfrom django.utils.translation import gettext_lazy as _\n\n\nclass DatePickerWidget(forms.DateInput):\n    def __init__(self, attrs=None, date_format=None):\n        attrs = attrs or {}\n        if 'placeholder' in attrs:\n            del attrs['placeholder']\n        date_attrs = dict(attrs)\n        date_attrs.setdefault('class', 'form-control')\n        date_attrs['class'] += ' datepickerfield'\n        date_attrs['autocomplete'] = 'off'\n\n        def placeholder():\n            df = date_format or get_format('DATE_INPUT_FORMATS')[0]\n            return now().replace(\n                year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0\n            ).strftime(df)\n\n        date_attrs['placeholder'] = lazy(placeholder, str)\n\n        forms.DateInput.__init__(self, date_attrs, date_format)\n\n\nclass TimePickerWidget(forms.TimeInput):\n    def __init__(self, attrs=None, time_format=None):\n        attrs = attrs or {}\n        if 'placeholder' in attrs:\n            del attrs['placeholder']\n        time_attrs = dict(attrs)\n        time_attrs.setdefault('class', 'form-control')\n        time_attrs['class'] += ' timepickerfield'\n        time_attrs['autocomplete'] = 'off'\n\n        def placeholder():\n            tf = time_format or get_format('TIME_INPUT_FORMATS')[0]\n            return now().replace(\n                year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0\n            ).strftime(tf)\n\n        time_attrs['placeholder'] = lazy(placeholder, str)\n\n        forms.TimeInput.__init__(self, time_attrs, time_format)\n\n\nclass UploadedFileWidget(forms.ClearableFileInput):\n    def __init__(self, *args, **kwargs):\n        self.position = kwargs.pop('position')\n        self.event = kwargs.pop('event')\n        self.answer = kwargs.pop('answer')\n        super().__init__(*args, **kwargs)\n\n    class FakeFile:\n        def __init__(self, file, position, event, answer):\n            self.file = file\n            self.position = position\n            self.event = event\n            self.answer = answer\n\n        def __str__(self):\n            return os.path.basename(self.file.name).split('.', 1)[-1]\n\n        @property\n        def url(self):\n            from pretix.base.models import OrderPosition\n            from pretix.multidomain.urlreverse import eventreverse\n\n            if isinstance(self.position, OrderPosition):\n                return eventreverse(self.event, 'presale:event.order.download.answer', kwargs={\n                    'order': self.position.order.code,\n                    'secret': self.position.order.secret,\n                    'answer': self.answer.pk,\n                })\n            else:\n                return eventreverse(self.event, 'presale:event.cart.download.answer', kwargs={\n                    'answer': self.answer.pk,\n                })\n\n    def get_context(self, name, value, attrs):\n        # Browsers can't recognize that the server already has a file uploaded\n        # Don't mark this input as being required if we already have an answer\n        # (this needs to be done via the attrs, otherwise we wouldn't get the \"required\" star on the field label)\n        ctx = super().get_context(name, value, attrs)\n        if ctx['widget']['is_initial']:\n            ctx['widget']['attrs']['required'] = False\n        return ctx\n\n    def format_value(self, value):\n        if self.is_initial(value):\n            return self.FakeFile(value, self.position, self.event, self.answer)\n\n\nclass SplitDateTimePickerWidget(forms.SplitDateTimeWidget):\n    template_name = 'pretixbase/forms/widgets/splitdatetime.html'\n\n    def __init__(self, attrs=None, date_format=None, time_format=None, min_date=None, max_date=None):\n        attrs = attrs or {}\n        if 'placeholder' in attrs:\n            del attrs['placeholder']\n        date_attrs = dict(attrs)\n        time_attrs = dict(attrs)\n        date_attrs.setdefault('class', 'form-control splitdatetimepart')\n        time_attrs.setdefault('class', 'form-control splitdatetimepart')\n        date_attrs.setdefault('autocomplete', 'off')\n        time_attrs.setdefault('autocomplete', 'off')\n        date_attrs['class'] += ' datepickerfield'\n        time_attrs['class'] += ' timepickerfield'\n        date_attrs['autocomplete'] = 'off'\n        time_attrs['autocomplete'] = 'off'\n        if min_date:\n            date_attrs['data-min'] = (\n                min_date if isinstance(min_date, date) else min_date.astimezone(get_current_timezone()).date()\n            ).isoformat()\n        if max_date:\n            date_attrs['data-max'] = (\n                max_date if isinstance(max_date, date) else max_date.astimezone(get_current_timezone()).date()\n            ).isoformat()\n\n        def date_placeholder():\n            df = date_format or get_format('DATE_INPUT_FORMATS')[0]\n            return now().replace(\n                year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0\n            ).strftime(df)\n\n        def time_placeholder():\n            tf = time_format or get_format('TIME_INPUT_FORMATS')[0]\n            return now().replace(\n                year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0\n            ).strftime(tf)\n\n        date_attrs['placeholder'] = lazy(date_placeholder, str)\n        time_attrs['placeholder'] = lazy(time_placeholder, str)\n\n        widgets = (\n            forms.DateInput(attrs=date_attrs, format=date_format),\n            forms.TimeInput(attrs=time_attrs, format=time_format),\n        )\n        # Skip one hierarchy level\n        forms.MultiWidget.__init__(self, widgets, attrs)\n\n\nclass BusinessBooleanRadio(forms.RadioSelect):\n    def __init__(self, require_business=False, attrs=None):\n        self.require_business = require_business\n        if self.require_business:\n            choices = (\n                ('business', _('Business or institutional customer')),\n            )\n        else:\n            choices = (\n                ('individual', _('Individual customer')),\n                ('business', _('Business or institutional customer')),\n            )\n        super().__init__(attrs, choices)\n\n    def format_value(self, value):\n        if self.require_business:\n            return 'business'\n        try:\n            return {True: 'business', False: 'individual'}[value]\n        except KeyError:\n            return 'individual'\n\n    def value_from_datadict(self, data, files, name):\n        value = data.get(name)\n        if self.require_business:\n            return True\n        return {\n            'business': True,\n            True: True,\n            'True': True,\n            'individual': False,\n            'False': False,\n            False: False,\n        }.get(value)\n", "path": "src/pretix/base/forms/widgets.py"}]}