diff --git a/src/pretix/control/forms/renderers.py b/src/pretix/control/forms/renderers.py
new file mode 100644
index 000000000..24d649c7c
--- /dev/null
+++ b/src/pretix/control/forms/renderers.py
@@ -0,0 +1,54 @@
+from bootstrap3.renderers import FieldRenderer
+from bootstrap3.text import text_value
+from django.forms import CheckboxInput
+from django.forms.utils import flatatt
+from django.utils.html import format_html
+from django.utils.safestring import mark_safe
+from django.utils.translation import pgettext
+from i18nfield.forms import I18nFormField
+
+
+def render_label(content, label_for=None, label_class=None, label_title='', optional=False):
+ """
+ Render a label with content
+ """
+ attrs = {}
+ if label_for:
+ attrs['for'] = label_for
+ if label_class:
+ attrs['class'] = label_class
+ if label_title:
+ attrs['title'] = label_title
+ builder = '<{tag}{attrs}>{content}{opt}{tag}>'
+ return format_html(
+ builder,
+ tag='label',
+ attrs=mark_safe(flatatt(attrs)) if attrs else '',
+ opt=mark_safe('
{}'.format(pgettext('form', 'Optional'))) if optional else '',
+ content=text_value(content),
+ )
+
+
+class ControlFieldRenderer(FieldRenderer):
+ def __init__(self, *args, **kwargs):
+ kwargs['layout'] = 'horizontal'
+ super().__init__(*args, **kwargs)
+
+ def add_label(self, html):
+ label = self.get_label()
+
+ if hasattr(self.field.field, '_required'):
+ # e.g. payment settings forms where a field is only required if the payment provider is active
+ required = self.field.field._required
+ elif isinstance(self.field.field, I18nFormField):
+ required = self.field.field.one_required
+ else:
+ required = self.field.field.required
+
+ html = render_label(
+ label,
+ label_for=self.field.id_for_label,
+ label_class=self.get_label_class(),
+ optional=not required and not isinstance(self.widget, CheckboxInput)
+ ) + html
+ return html
diff --git a/src/pretix/control/templates/pretixcontrol/event/display.html b/src/pretix/control/templates/pretixcontrol/event/display.html
index ca3781d82..dcca5883c 100644
--- a/src/pretix/control/templates/pretixcontrol/event/display.html
+++ b/src/pretix/control/templates/pretixcontrol/event/display.html
@@ -8,16 +8,16 @@
{% bootstrap_form_errors form %}
- {% bootstrap_field formset.empty_form.active layout='horizontal' %}
- {% bootstrap_field formset.empty_form.default_price addon_after=request.event.currency layout='horizontal' %}
- {% bootstrap_field formset.empty_form.description layout='horizontal' %}
+ {% bootstrap_field formset.empty_form.active layout="control" %}
+ {% bootstrap_field formset.empty_form.default_price addon_after=request.event.currency layout="control" %}
+ {% bootstrap_field formset.empty_form.description layout="control" %}
{% endescapescript %}
diff --git a/src/pretix/control/templates/pretixcontrol/items/category.html b/src/pretix/control/templates/pretixcontrol/items/category.html
index b19c67f68..29912eef5 100644
--- a/src/pretix/control/templates/pretixcontrol/items/category.html
+++ b/src/pretix/control/templates/pretixcontrol/items/category.html
@@ -11,9 +11,9 @@
{% if category %}
diff --git a/src/pretix/control/templates/pretixcontrol/items/question_edit.html b/src/pretix/control/templates/pretixcontrol/items/question_edit.html
index 15c435ecf..bf03685bb 100644
--- a/src/pretix/control/templates/pretixcontrol/items/question_edit.html
+++ b/src/pretix/control/templates/pretixcontrol/items/question_edit.html
@@ -20,14 +20,14 @@
{% bootstrap_form_errors form %}
{% blocktrans trimmed %}
diff --git a/src/pretix/control/templates/pretixcontrol/items/quota_edit.html b/src/pretix/control/templates/pretixcontrol/items/quota_edit.html
index 14ce8c46c..787cd6653 100644
--- a/src/pretix/control/templates/pretixcontrol/items/quota_edit.html
+++ b/src/pretix/control/templates/pretixcontrol/items/quota_edit.html
@@ -19,10 +19,10 @@
{% bootstrap_form_errors form %}
{% endif %}
- {% bootstrap_field add_form.do layout='horizontal' %}
- {% bootstrap_field add_form.itemvar layout='horizontal' %}
- {% bootstrap_field add_form.price addon_after=request.event.currency layout='horizontal' %}
+ {% bootstrap_field add_form.do layout="control" %}
+ {% bootstrap_field add_form.itemvar layout="control" %}
+ {% bootstrap_field add_form.price addon_after=request.event.currency layout="control" %}
{% if add_form.addon_to %}
- {% bootstrap_field add_form.addon_to layout='horizontal' %}
+ {% bootstrap_field add_form.addon_to layout="control" %}
{% endif %}
{% if add_form.subevent %}
- {% bootstrap_field add_form.subevent layout='horizontal' %}
+ {% bootstrap_field add_form.subevent layout="control" %}
{% endif %}
@@ -174,7 +174,7 @@
{{ other_form.custom_error }}
{% endif %}
- {% bootstrap_field other_form.recalculate_taxes layout='horizontal' %}
+ {% bootstrap_field other_form.recalculate_taxes layout="control" %}
diff --git a/src/pretix/control/templates/pretixcontrol/organizers/display.html b/src/pretix/control/templates/pretixcontrol/organizers/display.html
index 9e5e534f8..1ee47cd4c 100644
--- a/src/pretix/control/templates/pretixcontrol/organizers/display.html
+++ b/src/pretix/control/templates/pretixcontrol/organizers/display.html
@@ -7,10 +7,10 @@
{% endescapescript %}
@@ -120,7 +120,7 @@
diff --git a/src/pretix/control/templates/pretixcontrol/vouchers/bulk.html b/src/pretix/control/templates/pretixcontrol/vouchers/bulk.html
index bfc7b0880..46dc36413 100644
--- a/src/pretix/control/templates/pretixcontrol/vouchers/bulk.html
+++ b/src/pretix/control/templates/pretixcontrol/vouchers/bulk.html
@@ -32,15 +32,15 @@
- {% bootstrap_field form.codes layout="horizontal" %}
+ {% bootstrap_field form.codes layout="control" %}
- {% bootstrap_field form.max_usages layout="horizontal" %}
+ {% bootstrap_field form.max_usages layout="control" %}
{% eventsignal request.event "pretix.control.signals.voucher_form_html" form=form %}