def settings_form_fields(self): d = OrderedDict([ ('public_name', I18nFormField( label=_('Payment method name'), widget=I18nTextInput, )), ('checkout_description', I18nFormField( label=_('Payment process description during checkout'), help_text= _('This text will be shown during checkout when the user selects this payment method. ' 'It should give a short explanation on this payment method.' ), widget=I18nTextarea, )), ('email_instructions', I18nFormField( label=_( 'Payment process description in order confirmation emails' ), help_text= _('This text will be included for the {payment_info} placeholder in order confirmation ' 'mails. It should instruct the user on how to proceed with the payment. You can use' 'the placeholders {order}, {total}, {currency} and {total_with_currency}' ), widget=I18nTextarea, validators=[ PlaceholderValidator([ '{order}', '{total}', '{currency}', '{total_with_currency}' ]) ], )), ('pending_description', I18nFormField( label=_('Payment process description for pending orders'), help_text= _('This text will be shown on the order confirmation page for pending orders. ' 'It should instruct the user on how to proceed with the payment. You can use' 'the placeholders {order}, {total}, {currency} and {total_with_currency}' ), widget=I18nTextarea, validators=[ PlaceholderValidator([ '{order}', '{total}', '{currency}', '{total_with_currency}' ]) ], )), ] + list(super().settings_form_fields.items())) d.move_to_end('_enabled', last=False) return d
class ReviewSettingsForm(ReadOnlyFlag, I18nFormMixin, HierarkeyForm): review_score_mandatory = forms.BooleanField( label=_('Require a review score'), required=False ) review_text_mandatory = forms.BooleanField( label=_('Require a review text'), required=False ) review_help_text = I18nFormField( label=_('Help text for reviewers'), help_text=_( 'This text will be shown at the top of every review, as long as reviews can be created or edited.' ) + ' ' + phrases.base.use_markdown, widget=I18nTextarea, required=False, ) allow_override_votes = forms.BooleanField( label=_('Allow override votes'), help_text=_( 'Review teams can be assigned a fixed amount of "override votes": Positive or negative vetos each reviewer can assign.' ), required=False, ) review_min_score = forms.IntegerField( label=_('Minimum score'), help_text=_('The minimum score reviewers can assign') ) review_max_score = forms.IntegerField( label=_('Maximum score'), help_text=_('The maximum score reviewers can assign') ) def __init__(self, obj, *args, **kwargs): super().__init__(*args, obj=obj, **kwargs) if getattr(obj, 'slug'): additional = _( 'You can configure override votes <a href="{link}">in the team settings</a>.' ).format(link=obj.orga_urls.team_settings) self.fields['allow_override_votes'].help_text += f' {additional}' minimum = int(obj.settings.review_min_score) maximum = int(obj.settings.review_max_score) self.score_label_fields = [] for number in range(abs(maximum - minimum + 1)): index = minimum + number self.fields[f'review_score_name_{index}'] = forms.CharField( label=_('Score label ({})').format(index), help_text=_( 'Human readable explanation of what a score of "{}" actually means, e.g. "great!".' ).format(index), required=False, ) def clean(self): data = self.cleaned_data minimum = int(data.get('review_min_score')) maximum = int(data.get('review_max_score')) if minimum >= maximum: self.add_error('review_min_score', forms.ValidationError( _('Please assign a minimum score smaller than the maximum score!') )) return data
def settings_form_fields(self): form_field = I18nFormField( label=_('Bank account details'), widget=I18nTextarea, ) return OrderedDict( list(super().settings_form_fields.items()) + [('bank_details', form_field)] )
def settings_form_fields(self): form_field = I18nFormField( label=_('Payment information text'), widget=I18nTextarea, ) return OrderedDict( list(super().settings_form_fields.items()) + [('information_text', form_field)])
class ReviewSettingsForm(ReadOnlyFlag, I18nFormMixin, HierarkeyForm): review_score_mandatory = forms.BooleanField( label=_("Require a review score"), required=False) review_text_mandatory = forms.BooleanField( label=_("Require a review text"), required=False) review_help_text = I18nFormField( label=_("Help text for reviewers"), help_text= _("This text will be shown at the top of every review, as long as reviews can be created or edited." ) + " " + phrases.base.use_markdown, widget=I18nTextarea, required=False, )
def form_field(**kwargs): return I18nFormField( label=_('Bank account details'), widget=I18nTextarea, help_text=_('Include everything that your customers need to send you a bank transfer payment. Within SEPA ' 'countries, IBAN, BIC and account owner should suffice. If you have lots of international ' 'customers, they might also need your full address and your bank\'s full address.'), widget_kwargs={'attrs': { 'rows': '4', 'placeholder': _( 'e.g. IBAN: DE12 1234 5678 8765 4321\n' 'BIC: GENEXAMPLE1\n' 'Account owner: John Doe\n' 'Name of Bank: Professional Banking Institute Ltd., London' ) }}, **kwargs )
def settings_form_fields(self): form_field = I18nFormField( label=_('Cheque Payment Instructions'), widget=I18nTextarea, help_text= _('Include everything that your customers need to know about paying by cheque. Where the cheque should be sent, how it should be marked up, etc...' ), widget_kwargs={ 'attrs': { 'rows': '2', 'placeholder': _('Cheques should be made payable to Super Event Committee, and posted to: ...' ) } }) return OrderedDict( list(super().settings_form_fields.items()) + [('cheque_details', form_field)])
class ReviewSettingsForm(ReadOnlyFlag, I18nFormMixin, I18nHelpText, HierarkeyForm): review_score_mandatory = forms.BooleanField( label=_("Require a review score"), required=False) review_text_mandatory = forms.BooleanField( label=_("Require a review text"), required=False) review_score_aggregate = forms.ChoiceField( label=_("Score aggregation method"), required=True, choices=(("median", _("Median")), ("mean", _("Average (mean)"))), widget=forms.RadioSelect, ) review_help_text = I18nFormField( label=_("Help text for reviewers"), help_text= _("This text will be shown at the top of every review, as long as reviews can be created or edited." ) + " " + phrases.base.use_markdown, widget=I18nTextarea, required=False, )
def settings_form_fields(self): form_field = I18nFormField( label=_('College Bill Information'), widget=I18nTextarea, help_text= _('Include everything that your customers need to know about paying by college bill. ' 'For example, make it clear that this option should only be selected by current students ' 'of the college - other CRSIDs will be rejected by the accounts office, and their payment will fail.' ), widget_kwargs={ 'attrs': { 'rows': '2', 'placeholder': _('After completing your purchase, we will contact the college bursary, to ask that ' 'the value of your tickets be added to your college bill at the end of term.' ) } }) return OrderedDict( list(super().settings_form_fields.items()) + [('college_bill_details', form_field)])
def form_fields(): return OrderedDict([ ('ack', forms.BooleanField( label= _('I have understood that people will pay the ticket price directly to my bank account and ' 'pretix cannot automatically know what payments arrived. Therefore, I will either mark ' 'payments as complete manually, or regularly import a digital bank statement in order to ' 'give pretix the required information.'), required=True, )), ('bank_details_type', forms.ChoiceField(label=_('Bank account type'), widget=forms.RadioSelect, choices=( ('sepa', _('SEPA bank account')), ('other', _('Other bank account')), ), initial='sepa')), ('bank_details_sepa_name', forms.CharField( label=_('Name of account holder'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' }), required=False)), ('bank_details_sepa_iban', IBANFormField( label=_('IBAN'), required=False, widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' }), )), ('bank_details_sepa_bic', BICFormField( label=_('BIC'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' }), required=False)), ('bank_details_sepa_bank', forms.CharField( label=_('Name of bank'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' }), required=False)), ('bank_details', I18nFormField( label=_('Bank account details'), widget=I18nTextarea, help_text= _('Include everything else that your customers might need to send you a bank transfer payment. ' 'If you have lots of international customers, they might need your full address and your ' 'bank\'s full address.'), widget_kwargs={ 'attrs': { 'rows': '4', 'placeholder': _('For SEPA accounts, you can leave this empty. Otherwise, please add everything that ' 'your customers need to transfer the money, e.g. account numbers, routing numbers, ' 'addresses, etc.'), } }, required=False)), ('invoice_immediately', forms.BooleanField( label= _('Create an invoice for orders using bank transfer immediately if the event is otherwise ' 'configured to create invoices after payment is completed.' ), required=False, )), ('public_name', I18nFormField(label=_('Payment method name'), widget=I18nTextInput, required=False)), ('omit_hyphen', forms.BooleanField( label=_('Do not include hyphens in the payment reference.'), help_text=_('This is required in some countries.'), required=False)), ('include_invoice_number', forms.BooleanField( label=_('Include invoice number in the payment reference.'), required=False)), ('prefix', forms.CharField( label=_('Prefix for the payment reference'), required=False, )), ('pending_description', I18nFormField( label=_('Additional text to show on pending orders'), help_text=_( 'This text will be shown on the order confirmation page for pending orders in addition to ' 'the standard text.'), widget=I18nTextarea, required=False, )), ('refund_iban_blocklist', forms.CharField( label=_('IBAN blocklist for refunds'), required=False, widget=forms.Textarea, help_text= _('Put one IBAN or IBAN prefix per line. The system will not attempt to send refunds to any ' 'of these IBANs. Useful e.g. if you receive a lot of "forwarded payments" by a third-party payment ' 'provider. You can also list country codes such as "GB" if you never want to send refunds to ' 'IBANs from a specific country.'))), ])
class PublicVotingSettingsForm(I18nFormMixin, HierarkeyForm): public_voting_text = I18nFormField( help_text=_( "This text will be shown at the top of the public voting page.") + " " + phrases.base.use_markdown, label=_("Text"), widget=I18nTextarea, required=False, ) public_voting_start = forms.DateTimeField( help_text= _("No public votes will be possible before this time. Submissions will not be publicly visible." ), label=_("Start"), widget=forms.DateTimeInput(attrs={"class": "datetimepickerfield"}), ) public_voting_end = forms.DateTimeField( help_text= _("No public votes will be possible after this time. Submissions will not be publicly visible." ), label=_("End"), widget=forms.DateTimeInput(attrs={"class": "datetimepickerfield"}), ) public_voting_anonymize_speakers = forms.BooleanField( required=False, label=_("Anonymise content"), help_text=_( "Hide speaker names and use anonymized content where available?"), ) public_voting_show_session_image = forms.BooleanField( required=False, label=_("Show session image"), help_text=_("Show the session image if one was uploaded."), initial=True, ) public_voting_min_score = forms.IntegerField( label=_("Minimum score"), help_text=_("The minimum score voters can assign"), initial=1, ) public_voting_max_score = forms.IntegerField( label=_("Maximum score"), help_text=_("The maximum score voters can assign"), initial=3, ) def __init__(self, obj, *args, **kwargs): super().__init__(*args, obj=obj, **kwargs) minimum = obj.settings.public_voting_min_score maximum = obj.settings.public_voting_max_score minimum = int(minimum) if minimum is not None else 1 maximum = int(maximum) if maximum is not None else 3 for number in range(abs(maximum - minimum + 1)): index = minimum + number self.fields[f"public_voting_score_name_{index}"] = forms.CharField( label=_("Score label ({})").format(index), help_text= _('Human readable explanation of what a score of "{}" actually means, e.g. "great!".' ).format(index), required=False, ) def clean(self): data = self.cleaned_data minimum = int(data.get("public_voting_min_score")) maximum = int(data.get("public_voting_max_score")) if minimum >= maximum: self.add_error( "public_voting_min_score", forms.ValidationError( _("Please assign a minimum score smaller than the maximum score!" )), ) return data
def form_fields(): return OrderedDict([ ('ack', forms.BooleanField( label= _('I have understood that people will pay the ticket price directly to my bank account and ' 'pretix cannot automatically know what payments arrived. Therefore, I will either mark ' 'payments as complete manually, or regularly import a digital bank statement in order to ' 'give pretix the required information.'), required=True, )), ('bank_details_type', forms.ChoiceField( label=_('Bank account type'), widget=forms.RadioSelect, choices=( ('sepa', _('SEPA bank account') ), ( 'other', _('Other bank account')), ), initial='sepa')), ('bank_details_sepa_name', forms.CharField( label=_('Name of account holder'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' }), required=False)), ('bank_details_sepa_iban', IBANFormField( label=_('IBAN'), required=False, widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' }), )), ('bank_details_sepa_bic', BICFormField( label=_('BIC'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' }), required=False)), ('bank_details_sepa_bank', forms.CharField( label=_('Name of bank'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' }), required=False)), ('bank_details', I18nFormField( label=_('Bank account details'), widget=I18nTextarea, help_text= _('Include everything else that your customers might need to send you a bank transfer payment. ' 'If you have lots of international customers, they might need your full address and your ' 'bank\'s full address.'), widget_kwargs={ 'attrs': { 'rows': '4', 'placeholder': _('For SEPA accounts, you can leave this empty. Otherwise, please add everything that ' 'your customers need to transfer the money, e.g. account numbers, routing numbers, ' 'addresses, etc.'), } }, required=False)), ('public_name', I18nFormField(label=_('Payment method name'), widget=I18nTextInput, required=False)) ])
class CfPSettingsForm(ReadOnlyFlag, I18nFormMixin, HierarkeyForm): cfp_show_deadline = forms.BooleanField( label=_('Display deadline publicly'), required=False) review_deadline = forms.DateTimeField( label=_('Review deadline'), required=False, ) review_score_mandatory = forms.BooleanField( label=_('Require reviewers to submit a score'), required=False, ) review_text_mandatory = forms.BooleanField( label=_('Require reviewers to submit a text'), required=False, ) mail_on_new_submission = forms.BooleanField( label=_('Send mail on new submission'), help_text= _('If this setting is checked, you will receive an email to the organiser address for every received submission.' ), required=False) allow_override_votes = forms.BooleanField( label=_('Allow override votes'), help_text= _('Individual reviewers can be assigned a fixed amount of "override votes" (positive or negative vetos).' ), required=False, ) review_min_score = forms.IntegerField( label=_('Minimum score'), help_text=_('The minimum score reviewers can assign'), ) review_max_score = forms.IntegerField( label=_('Maximum score'), help_text=_('The maximum score reviewers can assign'), ) review_help_text = I18nFormField( label=_('Help text for reviewers'), help_text= _('This text will be shown at the top of every review, as long as reviews can be created or edited. You can use markdown here.' ), widget=I18nTextarea, required=False, ) def __init__(self, obj, *args, **kwargs): kwargs.pop('read_only' ) # added in ActionFromUrl view mixin, but not needed here. super().__init__(*args, obj=obj, **kwargs) if getattr(obj, 'email'): self.fields[ 'mail_on_new_submission'].help_text += f' (<a href="mailto:{obj.email}">{obj.email}</a>)' if getattr(obj, 'slug'): additional = _( 'You can configure override votes <a href="{link}">here</a>.' ).format(link=obj.orga_urls.team_settings) self.fields['allow_override_votes'].help_text += f' {additional}' minimum = int(obj.settings.review_min_score) maximum = int(obj.settings.review_max_score) self.fields['review_deadline'].widget = forms.DateTimeInput( attrs={'class': 'datetimepickerfield'}) for number in range(abs(maximum - minimum + 1)): index = minimum + number self.fields[f'review_score_name_{index}'] = forms.CharField( label=_('Score label ({})').format(index), help_text= _('Human readable explanation of what a score of "{}" actually means, e.g. "great!".' ).format(index), required=False) def clean(self): data = self.cleaned_data minimum = int(data.get('review_min_score')) maximum = int(data.get('review_max_score')) if not minimum < maximum: raise forms.ValidationError( _('Please assign a minimum score smaller than the maximum score!' )) return data
def form_fields(): return OrderedDict([ ('bank_details_type', forms.ChoiceField( label=_('Bank account type'), widget=forms.RadioSelect, choices=( ('sepa', _('SEPA bank account')), ('other', _('Other bank account')), ), initial='sepa' )), ('bank_details_sepa_name', forms.CharField( label=_('Name of account holder'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' } ), required=False )), ('bank_details_sepa_iban', IBANFormField( label=_('IBAN'), required=False, widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' } ), )), ('bank_details_sepa_bic', BICFormField( label=_('BIC'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' } ), required=False )), ('bank_details_sepa_bank', forms.CharField( label=_('Name of bank'), widget=forms.TextInput( attrs={ 'data-display-dependency': '#id_payment_banktransfer_bank_details_type_0', 'data-required-if': '#id_payment_banktransfer_bank_details_type_0' } ), required=False )), ('bank_details', I18nFormField( label=_('Bank account details'), widget=I18nTextarea, help_text=_( 'Include everything else that your customers might need to send you a bank transfer payment. ' 'If you have lots of international customers, they might need your full address and your ' 'bank\'s full address.'), widget_kwargs={'attrs': { 'rows': '4', 'placeholder': _( 'For SEPA accounts, you can leave this empty. Otherwise, please add everything that ' 'your customers need to transfer the money, e.g. account numbers, routing numbers, ' 'addresses, etc.' ), }}, required=False )), ('public_name', I18nFormField( label=_('Payment method name'), widget=I18nTextInput, required=False )) ])
class CfPSettingsForm(ReadOnlyFlag, I18nFormMixin, HierarkeyForm): cfp_show_deadline = forms.BooleanField( label=_('Display deadline publicly'), required=False) cfp_request_abstract = forms.BooleanField(label=_('Offer data entry'), required=False) cfp_request_description = forms.BooleanField(label=_('Offer data entry'), required=False) cfp_request_notes = forms.BooleanField(label=_('Offer data entry'), required=False) cfp_request_biography = forms.BooleanField(label=_('Offer data entry'), required=False) cfp_request_availabilities = forms.BooleanField( label=_('Offer data entry'), required=False) cfp_request_do_not_record = forms.BooleanField(label=_('Offer data entry'), required=False) cfp_request_image = forms.BooleanField(label=_('Offer data entry'), required=False) cfp_require_abstract = forms.BooleanField(label=_('Force data entry'), required=False) cfp_require_description = forms.BooleanField(label=_('Force data entry'), required=False) cfp_require_notes = forms.BooleanField(label=_('Force data entry'), required=False) cfp_require_biography = forms.BooleanField(required=False) cfp_require_availabilities = forms.BooleanField(required=False) cfp_require_image = forms.BooleanField(label=_('Force data entry'), required=False) cfp_abstract_min_length = forms.IntegerField(label=_('Minimum length'), required=False, min_value=0) cfp_description_min_length = forms.IntegerField(label=_('Minimum length'), required=False, min_value=0) cfp_biography_min_length = forms.IntegerField(label=_('Minimum length'), required=False, min_value=0) cfp_abstract_max_length = forms.IntegerField(label=_('Maximum length'), required=False, min_value=0) cfp_description_max_length = forms.IntegerField(label=_('Maximum length'), required=False, min_value=0) cfp_biography_max_length = forms.IntegerField(label=_('Maximum length'), required=False, min_value=0) review_deadline = forms.DateTimeField(label=_('Review deadline'), required=False) review_score_mandatory = forms.BooleanField( label=_('Require a review score'), required=False) review_text_mandatory = forms.BooleanField( label=_('Require a review text'), required=False) mail_on_new_submission = forms.BooleanField( label=_('Send mail on new submission'), help_text= _('If this setting is checked, you will receive an email to the organiser address for every received submission.' ), required=False, ) allow_override_votes = forms.BooleanField( label=_('Allow override votes'), help_text= _('Review teams can be assigned a fixed amount of "override votes": Positive or negative vetos each reviewer can assign.' ), required=False, ) review_min_score = forms.IntegerField( label=_('Minimum score'), help_text=_('The minimum score reviewers can assign')) review_max_score = forms.IntegerField( label=_('Maximum score'), help_text=_('The maximum score reviewers can assign')) review_help_text = I18nFormField( label=_('Help text for reviewers'), help_text= _('This text will be shown at the top of every review, as long as reviews can be created or edited.' ) + ' ' + phrases.base.use_markdown, widget=I18nTextarea, required=False, ) def __init__(self, obj, *args, **kwargs): kwargs.pop('read_only' ) # added in ActionFromUrl view mixin, but not needed here. super().__init__(*args, obj=obj, **kwargs) if getattr(obj, 'email'): self.fields[ 'mail_on_new_submission'].help_text += f' (<a href="mailto:{obj.email}">{obj.email}</a>)' if getattr(obj, 'slug'): additional = _( 'You can configure override votes <a href="{link}">in the team settings</a>.' ).format(link=obj.orga_urls.team_settings) self.fields['allow_override_votes'].help_text += f' {additional}' minimum = int(obj.settings.review_min_score) maximum = int(obj.settings.review_max_score) self.fields['review_deadline'].widget = forms.DateTimeInput( attrs={'class': 'datetimepickerfield'}) for number in range(abs(maximum - minimum + 1)): index = minimum + number self.fields[f'review_score_name_{index}'] = forms.CharField( label=_('Score label ({})').format(index), help_text= _('Human readable explanation of what a score of "{}" actually means, e.g. "great!".' ).format(index), required=False, ) for field in ['abstract', 'description', 'biography']: self.fields[f'cfp_{field}_min_length'].widget.attrs[ 'placeholder'] = '' self.fields[f'cfp_{field}_max_length'].widget.attrs[ 'placeholder'] = '' def clean(self): data = self.cleaned_data minimum = int(data.get('review_min_score')) maximum = int(data.get('review_max_score')) if minimum >= maximum: raise forms.ValidationError( _('Please assign a minimum score smaller than the maximum score!' )) return data
class CfPSettingsForm(ReadOnlyFlag, I18nFormMixin, HierarkeyForm): cfp_show_deadline = forms.BooleanField( label=_('Display deadline publicly'), required=False) review_deadline = forms.DateTimeField( label=_('Review deadline'), required=False, ) review_score_mandatory = forms.BooleanField( label=_('Require reviewers to submit a score'), required=False, ) review_text_mandatory = forms.BooleanField( label=_('Require reviewers to submit a text'), required=False, ) mail_on_new_submission = forms.BooleanField( label=_('Send mail on new submission'), help_text= _('If this setting is checked, you will receive an email to the orga address for every received submission.' ), required=False) allow_override_votes = forms.BooleanField( label=_('Allow override votes'), help_text= _('With this setting, individual reviewers can be assigned a fixed amount of "override votes" functioning like vetos.' ), required=False, ) review_min_score = forms.IntegerField( label=_('Minimum score'), help_text=_('The minimum score reviewers can assign'), ) review_max_score = forms.IntegerField( label=_('Maximum score'), help_text=_('The maximum score reviewers can assign'), ) review_help_text = I18nFormField( label=_('Help text for reviewers'), help_text= _('This text will be shown at the top of every review, as long as reviews can be created or edited. You can use markdown here.' ), widget=I18nTextarea, required=False, ) def __init__(self, obj, *args, **kwargs): kwargs.pop('read_only' ) # added in ActionFromUrl view mixin, but not needed here. super().__init__(*args, obj=obj, **kwargs) minimum = int(obj.settings.review_min_score) maximum = int(obj.settings.review_max_score) self.fields['review_deadline'].widget = forms.DateTimeInput( attrs={'class': 'datetimepickerfield'}) for number in range(abs(maximum - minimum + 1)): index = minimum + number self.fields[f'review_score_name_{index}'] = forms.CharField( label=_('Score label ({})').format(index), required=False) def clean(self): data = self.cleaned_data minimum = int(data.get('review_min_score')) maximum = int(data.get('review_max_score')) if not minimum < maximum: raise forms.ValidationError( _('Please assign a minimum score smaller than the maximum score!' )) return data