forked from CGM_Public/pretix_original
Compare commits
2 Commits
fix-checkb
...
fix-pdf-bg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
105b60855a | ||
|
|
7338381e58 |
@@ -1,112 +0,0 @@
|
|||||||
from bootstrap3.renderers import FieldRenderer
|
|
||||||
from bootstrap3.text import text_value
|
|
||||||
from django.forms import CheckboxInput, CheckboxSelectMultiple, RadioSelect
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
def render_label(content, label_for=None, label_class=None, label_title='', label_id='', optional=False, is_valid=None, attrs=None):
|
|
||||||
"""
|
|
||||||
Render a label with content
|
|
||||||
"""
|
|
||||||
attrs = attrs or {}
|
|
||||||
if label_for:
|
|
||||||
attrs['for'] = label_for
|
|
||||||
if label_class:
|
|
||||||
attrs['class'] = label_class
|
|
||||||
if label_title:
|
|
||||||
attrs['title'] = label_title
|
|
||||||
if label_id:
|
|
||||||
attrs['id'] = label_id
|
|
||||||
|
|
||||||
opt = ""
|
|
||||||
|
|
||||||
if is_valid is not None:
|
|
||||||
if is_valid:
|
|
||||||
validation_text = pgettext('form', 'is valid')
|
|
||||||
else:
|
|
||||||
validation_text = pgettext('form', 'has errors')
|
|
||||||
opt += '<strong class="sr-only"> {}</strong>'.format(validation_text)
|
|
||||||
|
|
||||||
if text_value(content) == ' ':
|
|
||||||
# Empty label, e.g. checkbox
|
|
||||||
attrs.setdefault('class', '')
|
|
||||||
attrs['class'] += ' label-empty'
|
|
||||||
# usually checkboxes have overall empty labels and special labels per checkbox
|
|
||||||
# => remove for-attribute as well as "required"-text appended to label
|
|
||||||
if 'for' in attrs:
|
|
||||||
del attrs['for']
|
|
||||||
else:
|
|
||||||
opt += '<i class="sr-only label-required">, {}</i>'.format(pgettext('form', 'required')) if not optional else ''
|
|
||||||
|
|
||||||
builder = '<{tag}{attrs}>{content}{opt}</{tag}>'
|
|
||||||
return format_html(
|
|
||||||
builder,
|
|
||||||
tag='label',
|
|
||||||
attrs=mark_safe(flatatt(attrs)) if attrs else '',
|
|
||||||
opt=mark_safe(opt),
|
|
||||||
content=text_value(content),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PretixFieldRenderer(FieldRenderer):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
kwargs['layout'] = 'horizontal'
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.is_group_widget = isinstance(self.widget, (CheckboxSelectMultiple, RadioSelect, )) or (self.is_multi_widget and len(self.widget.widgets) > 1)
|
|
||||||
|
|
||||||
def add_label(self, html):
|
|
||||||
attrs = {}
|
|
||||||
label = self.get_label()
|
|
||||||
|
|
||||||
if hasattr(self.field.field, '_show_required'):
|
|
||||||
# e.g. payment settings forms where a field is only required if the payment provider is active
|
|
||||||
required = self.field.field._show_required
|
|
||||||
elif 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
|
|
||||||
else:
|
|
||||||
required = self.field.field.required
|
|
||||||
|
|
||||||
if self.field.form.is_bound:
|
|
||||||
is_valid = len(self.field.errors) == 0
|
|
||||||
else:
|
|
||||||
is_valid = None
|
|
||||||
|
|
||||||
if self.is_group_widget:
|
|
||||||
label_for = ""
|
|
||||||
label_id = "legend-{}".format(self.field.html_name)
|
|
||||||
else:
|
|
||||||
label_for = self.field.id_for_label
|
|
||||||
label_id = ""
|
|
||||||
|
|
||||||
if hasattr(self.field.field, 'question') and self.field.field.question.identifier:
|
|
||||||
attrs["data-identifier"] = self.field.field.question.identifier
|
|
||||||
|
|
||||||
html = render_label(
|
|
||||||
label,
|
|
||||||
label_for=label_for,
|
|
||||||
label_class=self.get_label_class(),
|
|
||||||
label_id=label_id,
|
|
||||||
attrs=attrs,
|
|
||||||
optional=not required and not isinstance(self.widget, CheckboxInput),
|
|
||||||
is_valid=is_valid
|
|
||||||
) + html
|
|
||||||
return html
|
|
||||||
|
|
||||||
def wrap_label_and_field(self, html):
|
|
||||||
if self.is_group_widget:
|
|
||||||
attrs = ' role="group" aria-labelledby="legend-{}"'.format(self.field.html_name)
|
|
||||||
else:
|
|
||||||
attrs = ''
|
|
||||||
return '<div class="{klass}"{attrs}>{html}</div>'.format(klass=self.get_form_group_class(), html=html, attrs=attrs)
|
|
||||||
|
|
||||||
def wrap_widget(self, html):
|
|
||||||
if isinstance(self.widget, CheckboxInput):
|
|
||||||
css_class = "checkbox"
|
|
||||||
if self.field.field.disabled:
|
|
||||||
css_class += " disabled"
|
|
||||||
html = f'<div class="{css_class}">{html}</div>'
|
|
||||||
return html
|
|
||||||
@@ -1092,10 +1092,20 @@ class Renderer:
|
|||||||
fg_num_pages = fg_pdf.get_num_pages()
|
fg_num_pages = fg_pdf.get_num_pages()
|
||||||
bg_num_pages = self.bg_pdf.get_num_pages()
|
bg_num_pages = self.bg_pdf.get_num_pages()
|
||||||
bg_pdf_to_merge = PdfWriter()
|
bg_pdf_to_merge = PdfWriter()
|
||||||
bg_pdf_to_merge.append(self.bg_pdf, pages=(0, min(bg_num_pages, fg_num_pages)))
|
bg_pdf_to_merge.append(
|
||||||
|
self.bg_pdf,
|
||||||
|
pages=(0, min(bg_num_pages, fg_num_pages)),
|
||||||
|
import_outline=False,
|
||||||
|
excluded_fields=("/Annots", "/B")
|
||||||
|
)
|
||||||
if fg_num_pages > bg_num_pages:
|
if fg_num_pages > bg_num_pages:
|
||||||
# repeat last page in bg_pdf to match fg_pdf
|
# repeat last page in bg_pdf to match fg_pdf
|
||||||
bg_pdf_to_merge.append(bg_pdf_to_merge, pages=[bg_num_pages - 1] * (fg_num_pages - bg_num_pages))
|
bg_pdf_to_merge.append(
|
||||||
|
bg_pdf_to_merge,
|
||||||
|
pages=[bg_num_pages - 1] * (fg_num_pages - bg_num_pages),
|
||||||
|
import_outline=False,
|
||||||
|
excluded_fields=("/Annots", "/B")
|
||||||
|
)
|
||||||
|
|
||||||
bg_pdf_to_merge.write(bg_filename)
|
bg_pdf_to_merge.write(bg_filename)
|
||||||
|
|
||||||
@@ -1162,7 +1172,12 @@ def merge_background(fg_pdf: PdfWriter, bg_pdf: PdfWriter, out_file, compress):
|
|||||||
bg_num_pages = bg_pdf.get_num_pages()
|
bg_num_pages = bg_pdf.get_num_pages()
|
||||||
if fg_num_pages > bg_num_pages:
|
if fg_num_pages > bg_num_pages:
|
||||||
# repeat last page in bg_pdf to match fg_pdf
|
# repeat last page in bg_pdf to match fg_pdf
|
||||||
bg_pdf.append(bg_pdf, pages=[bg_num_pages - 1] * (fg_num_pages - bg_num_pages))
|
bg_pdf.append(
|
||||||
|
bg_pdf,
|
||||||
|
pages=[bg_num_pages - 1] * (fg_num_pages - bg_num_pages),
|
||||||
|
import_outline=False,
|
||||||
|
excluded_fields=("/Annots", "/B")
|
||||||
|
)
|
||||||
|
|
||||||
bg_pdf.write(bg_filename)
|
bg_pdf.write(bg_filename)
|
||||||
|
|
||||||
|
|||||||
@@ -21,16 +21,82 @@
|
|||||||
#
|
#
|
||||||
from bootstrap3.renderers import FieldRenderer, InlineFieldRenderer
|
from bootstrap3.renderers import FieldRenderer, InlineFieldRenderer
|
||||||
from bootstrap3.text import text_value
|
from bootstrap3.text import text_value
|
||||||
|
from django.forms import CheckboxInput, CheckboxSelectMultiple, RadioSelect
|
||||||
from django.forms.utils import flatatt
|
from django.forms.utils import flatatt
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import pgettext
|
from django.utils.translation import pgettext
|
||||||
|
from i18nfield.forms import I18nFormField
|
||||||
from pretix.base.forms.renderers import PretixFieldRenderer
|
|
||||||
|
|
||||||
|
|
||||||
class ControlFieldRenderer(PretixFieldRenderer):
|
def render_label(content, label_for=None, label_class=None, label_title='', label_id='', optional=False):
|
||||||
pass
|
"""
|
||||||
|
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
|
||||||
|
if label_id:
|
||||||
|
attrs['id'] = label_id
|
||||||
|
|
||||||
|
if text_value(content) == ' ':
|
||||||
|
# Empty label, e.g. checkbox
|
||||||
|
attrs.setdefault('class', '')
|
||||||
|
attrs['class'] += ' label-empty'
|
||||||
|
|
||||||
|
builder = '<{tag}{attrs}>{content}{opt}</{tag}>'
|
||||||
|
return format_html(
|
||||||
|
builder,
|
||||||
|
tag='label',
|
||||||
|
attrs=mark_safe(flatatt(attrs)) if attrs else '',
|
||||||
|
opt=mark_safe('<br><span class="optional">{}</span>'.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)
|
||||||
|
self.is_group_widget = isinstance(self.widget, (CheckboxSelectMultiple, RadioSelect, )) or (self.is_multi_widget and len(self.widget.widgets) > 1)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if self.is_group_widget:
|
||||||
|
label_for = ""
|
||||||
|
label_id = "legend-{}".format(self.field.html_name)
|
||||||
|
else:
|
||||||
|
label_for = self.field.id_for_label
|
||||||
|
label_id = ""
|
||||||
|
|
||||||
|
html = render_label(
|
||||||
|
label,
|
||||||
|
label_for=label_for,
|
||||||
|
label_class=self.get_label_class(),
|
||||||
|
label_id=label_id,
|
||||||
|
optional=not required and not isinstance(self.widget, CheckboxInput)
|
||||||
|
) + html
|
||||||
|
return html
|
||||||
|
|
||||||
|
def wrap_label_and_field(self, html):
|
||||||
|
if self.is_group_widget:
|
||||||
|
attrs = ' role="group" aria-labelledby="legend-{}"'.format(self.field.html_name)
|
||||||
|
else:
|
||||||
|
attrs = ''
|
||||||
|
return '<div class="{klass}"{attrs}>{html}</div>'.format(klass=self.get_form_group_class(), html=html, attrs=attrs)
|
||||||
|
|
||||||
|
|
||||||
class ControlFieldWithVisibilityRenderer(ControlFieldRenderer):
|
class ControlFieldWithVisibilityRenderer(ControlFieldRenderer):
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ logger = logging.getLogger('pretix.plugins.stripe')
|
|||||||
# - PayNow: ✗
|
# - PayNow: ✗
|
||||||
# - UPI: ✗
|
# - UPI: ✗
|
||||||
# - Netbanking: ✗
|
# - Netbanking: ✗
|
||||||
|
# - TWINT: ✓
|
||||||
#
|
#
|
||||||
# Bank transfers
|
# Bank transfers
|
||||||
# - ACH Bank Transfer: ✗
|
# - ACH Bank Transfer: ✗
|
||||||
@@ -448,6 +449,14 @@ class StripeSettingsHolder(BasePaymentProvider):
|
|||||||
'before they work properly.'),
|
'before they work properly.'),
|
||||||
required=False,
|
required=False,
|
||||||
)),
|
)),
|
||||||
|
('method_twint',
|
||||||
|
forms.BooleanField(
|
||||||
|
label='TWINT',
|
||||||
|
disabled=self.event.currency != 'CHF',
|
||||||
|
help_text=_('Some payment methods might need to be enabled in the settings of your Stripe account '
|
||||||
|
'before they work properly.'),
|
||||||
|
required=False,
|
||||||
|
)),
|
||||||
('method_affirm',
|
('method_affirm',
|
||||||
forms.BooleanField(
|
forms.BooleanField(
|
||||||
label=_('Affirm'),
|
label=_('Affirm'),
|
||||||
@@ -1793,3 +1802,25 @@ class StripeSwish(StripeRedirectMethod):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class StripeTwint(StripeRedirectMethod):
|
||||||
|
identifier = 'stripe_twint'
|
||||||
|
verbose_name = _('TWINT via Stripe')
|
||||||
|
public_name = 'TWINT'
|
||||||
|
method = 'twint'
|
||||||
|
confirmation_method = 'automatic'
|
||||||
|
explanation = _(
|
||||||
|
'This payment method is available to users of the Swiss app TWINT. Please have your app '
|
||||||
|
'ready.'
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_allowed(self, request: HttpRequest, total: Decimal=None) -> bool:
|
||||||
|
return super().is_allowed(request, total) and request.event.currency == "CHF" and total <= Decimal("5000.00")
|
||||||
|
|
||||||
|
def _payment_intent_kwargs(self, request, payment):
|
||||||
|
return {
|
||||||
|
"payment_method_data": {
|
||||||
|
"type": "twint",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,13 +48,14 @@ def register_payment_provider(sender, **kwargs):
|
|||||||
StripeAffirm, StripeAlipay, StripeBancontact, StripeCC, StripeEPS,
|
StripeAffirm, StripeAlipay, StripeBancontact, StripeCC, StripeEPS,
|
||||||
StripeGiropay, StripeIdeal, StripeKlarna, StripeMultibanco,
|
StripeGiropay, StripeIdeal, StripeKlarna, StripeMultibanco,
|
||||||
StripePayPal, StripePrzelewy24, StripeSEPADirectDebit,
|
StripePayPal, StripePrzelewy24, StripeSEPADirectDebit,
|
||||||
StripeSettingsHolder, StripeSofort, StripeSwish, StripeWeChatPay,
|
StripeSettingsHolder, StripeSofort, StripeSwish, StripeTwint,
|
||||||
|
StripeWeChatPay,
|
||||||
)
|
)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
StripeSettingsHolder, StripeCC, StripeGiropay, StripeIdeal, StripeAlipay, StripeBancontact,
|
StripeSettingsHolder, StripeCC, StripeGiropay, StripeIdeal, StripeAlipay, StripeBancontact,
|
||||||
StripeSofort, StripeEPS, StripeMultibanco, StripePrzelewy24, StripeWeChatPay,
|
StripeSofort, StripeEPS, StripeMultibanco, StripePrzelewy24, StripeWeChatPay,
|
||||||
StripeSEPADirectDebit, StripeAffirm, StripeKlarna, StripePayPal, StripeSwish
|
StripeSEPADirectDebit, StripeAffirm, StripeKlarna, StripePayPal, StripeSwish, StripeTwint,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,14 +19,66 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||||
# <https://www.gnu.org/licenses/>.
|
# <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
from bootstrap3.renderers import FieldRenderer
|
||||||
|
from bootstrap3.text import text_value
|
||||||
from bootstrap3.utils import add_css_class
|
from bootstrap3.utils import add_css_class
|
||||||
from django.utils.html import escape, strip_tags
|
from django.forms import CheckboxInput, CheckboxSelectMultiple, RadioSelect
|
||||||
|
from django.forms.utils import flatatt
|
||||||
|
from django.utils.html import escape, format_html, strip_tags
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
from django.utils.translation import pgettext
|
||||||
from pretix.base.forms.renderers import PretixFieldRenderer
|
|
||||||
|
|
||||||
|
|
||||||
class CheckoutFieldRenderer(PretixFieldRenderer):
|
def render_label(content, label_for=None, label_class=None, label_title='', label_id='', optional=False, is_valid=None, attrs=None):
|
||||||
|
"""
|
||||||
|
Render a label with content
|
||||||
|
"""
|
||||||
|
attrs = attrs or {}
|
||||||
|
if label_for:
|
||||||
|
attrs['for'] = label_for
|
||||||
|
if label_class:
|
||||||
|
attrs['class'] = label_class
|
||||||
|
if label_title:
|
||||||
|
attrs['title'] = label_title
|
||||||
|
if label_id:
|
||||||
|
attrs['id'] = label_id
|
||||||
|
|
||||||
|
opt = ""
|
||||||
|
|
||||||
|
if is_valid is not None:
|
||||||
|
if is_valid:
|
||||||
|
validation_text = pgettext('form', 'is valid')
|
||||||
|
else:
|
||||||
|
validation_text = pgettext('form', 'has errors')
|
||||||
|
opt += '<strong class="sr-only"> {}</strong>'.format(validation_text)
|
||||||
|
|
||||||
|
if text_value(content) == ' ':
|
||||||
|
# Empty label, e.g. checkbox
|
||||||
|
attrs.setdefault('class', '')
|
||||||
|
attrs['class'] += ' label-empty'
|
||||||
|
# usually checkboxes have overall empty labels and special labels per checkbox
|
||||||
|
# => remove for-attribute as well as "required"-text appended to label
|
||||||
|
if 'for' in attrs:
|
||||||
|
del attrs['for']
|
||||||
|
else:
|
||||||
|
opt += '<i class="sr-only label-required">, {}</i>'.format(pgettext('form', 'required')) if not optional else ''
|
||||||
|
|
||||||
|
builder = '<{tag}{attrs}>{content}{opt}</{tag}>'
|
||||||
|
return format_html(
|
||||||
|
builder,
|
||||||
|
tag='label',
|
||||||
|
attrs=mark_safe(flatatt(attrs)) if attrs else '',
|
||||||
|
opt=mark_safe(opt),
|
||||||
|
content=text_value(content),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CheckoutFieldRenderer(FieldRenderer):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['layout'] = 'horizontal'
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.is_group_widget = isinstance(self.widget, (CheckboxSelectMultiple, RadioSelect, )) or (self.is_multi_widget and len(self.widget.widgets) > 1)
|
||||||
|
|
||||||
def get_form_group_class(self):
|
def get_form_group_class(self):
|
||||||
form_group_class = self.form_group_class
|
form_group_class = self.form_group_class
|
||||||
if self.field.errors:
|
if self.field.errors:
|
||||||
@@ -69,6 +121,45 @@ class CheckoutFieldRenderer(PretixFieldRenderer):
|
|||||||
help_ids = ["help-for-{id}-{idx}".format(id=self.field.id_for_label, idx=idx) for idx in range(help_cnt)]
|
help_ids = ["help-for-{id}-{idx}".format(id=self.field.id_for_label, idx=idx) for idx in range(help_cnt)]
|
||||||
widget.attrs["aria-describedby"] = " ".join(help_ids)
|
widget.attrs["aria-describedby"] = " ".join(help_ids)
|
||||||
|
|
||||||
|
def add_label(self, html):
|
||||||
|
attrs = {}
|
||||||
|
label = self.get_label()
|
||||||
|
|
||||||
|
if hasattr(self.field.field, '_show_required'):
|
||||||
|
# e.g. payment settings forms where a field is only required if the payment provider is active
|
||||||
|
required = self.field.field._show_required
|
||||||
|
elif 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
|
||||||
|
else:
|
||||||
|
required = self.field.field.required
|
||||||
|
|
||||||
|
if self.field.form.is_bound:
|
||||||
|
is_valid = len(self.field.errors) == 0
|
||||||
|
else:
|
||||||
|
is_valid = None
|
||||||
|
|
||||||
|
if self.is_group_widget:
|
||||||
|
label_for = ""
|
||||||
|
label_id = "legend-{}".format(self.field.html_name)
|
||||||
|
else:
|
||||||
|
label_for = self.field.id_for_label
|
||||||
|
label_id = ""
|
||||||
|
|
||||||
|
if hasattr(self.field.field, 'question') and self.field.field.question.identifier:
|
||||||
|
attrs["data-identifier"] = self.field.field.question.identifier
|
||||||
|
|
||||||
|
html = render_label(
|
||||||
|
label,
|
||||||
|
label_for=label_for,
|
||||||
|
label_class=self.get_label_class(),
|
||||||
|
label_id=label_id,
|
||||||
|
attrs=attrs,
|
||||||
|
optional=not required and not isinstance(self.widget, CheckboxInput),
|
||||||
|
is_valid=is_valid
|
||||||
|
) + html
|
||||||
|
return html
|
||||||
|
|
||||||
def put_inside_label(self, html):
|
def put_inside_label(self, html):
|
||||||
content = "{field} {label}".format(field=html, label=self.label)
|
content = "{field} {label}".format(field=html, label=self.label)
|
||||||
return render_label(
|
return render_label(
|
||||||
@@ -76,3 +167,10 @@ class CheckoutFieldRenderer(PretixFieldRenderer):
|
|||||||
label_for=self.field.id_for_label,
|
label_for=self.field.id_for_label,
|
||||||
label_title=escape(strip_tags(self.field_help)),
|
label_title=escape(strip_tags(self.field_help)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def wrap_label_and_field(self, html):
|
||||||
|
if self.is_group_widget:
|
||||||
|
attrs = ' role="group" aria-labelledby="legend-{}"'.format(self.field.html_name)
|
||||||
|
else:
|
||||||
|
attrs = ''
|
||||||
|
return '<div class="{klass}"{attrs}>{html}</div>'.format(klass=self.get_form_group_class(), html=html, attrs=attrs)
|
||||||
|
|||||||
Reference in New Issue
Block a user