From 6c0ffe2f417bdd6463d87905844ddb86b112cc96 Mon Sep 17 00:00:00 2001
From: David Smith <39445562+smithdc1@users.noreply.github.com>
Date: Wed, 26 Feb 2020 20:07:34 +0000
Subject: [PATCH] Apply Black to entire codebase (#990)
* Apply Black to entire codebase
* Add Black GitHub Action
---
.github/workflows/black.yml | 22 +
README.rst | 3 +
crispy_forms/__init__.py | 2 +-
crispy_forms/base.py | 1 +
crispy_forms/bootstrap.py | 180 ++---
crispy_forms/exceptions.py | 1 +
crispy_forms/helper.py | 141 ++--
crispy_forms/layout.py | 158 +++--
crispy_forms/layout_slice.py | 32 +-
.../templatetags/crispy_forms_field.py | 57 +-
.../templatetags/crispy_forms_filters.py | 56 +-
.../templatetags/crispy_forms_tags.py | 97 ++-
.../templatetags/crispy_forms_utils.py | 6 +-
crispy_forms/tests/conftest.py | 31 +-
crispy_forms/tests/forms.py | 73 +-
crispy_forms/tests/test_dynamic_api.py | 413 ++++--------
crispy_forms/tests/test_form_helper.py | 628 +++++++++---------
crispy_forms/tests/test_layout.py | 553 ++++++---------
crispy_forms/tests/test_layout_objects.py | 276 ++++----
crispy_forms/tests/test_settings.py | 53 +-
crispy_forms/tests/test_tags.py | 144 ++--
crispy_forms/tests/test_utils.py | 12 +-
crispy_forms/tests/urls.py | 2 +-
crispy_forms/tests/utils.py | 10 +-
crispy_forms/utils.py | 65 +-
pyproject.toml | 3 +
setup.cfg | 3 +-
27 files changed, 1358 insertions(+), 1664 deletions(-)
create mode 100644 .github/workflows/black.yml
create mode 100644 pyproject.toml
diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml
new file mode 100644
index 000000000..e10c93d02
--- /dev/null
+++ b/.github/workflows/black.yml
@@ -0,0 +1,22 @@
+name: black
+
+on: [push, pull_request]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v1
+ with:
+ python-version: 3.8
+ - name: Install Black
+ run: |
+ python -m pip install --upgrade pip
+ pip install Black
+ - name: run black
+ run: |
+ black crispy_forms --check
diff --git a/README.rst b/README.rst
index a4a8a4197..724eaa6e9 100644
--- a/README.rst
+++ b/README.rst
@@ -6,6 +6,9 @@ django-crispy-forms
:alt: Build Status
:target: https://travis-ci.org/django-crispy-forms/django-crispy-forms
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/psf/black
+
.. image:: http://codecov.io/github/django-crispy-forms/django-crispy-forms/coverage.svg?branch=master
:target: http://codecov.io/github/django-crispy-forms/django-crispy-forms?branch=master
diff --git a/crispy_forms/__init__.py b/crispy_forms/__init__.py
index e8b6b090b..2d986fc50 100644
--- a/crispy_forms/__init__.py
+++ b/crispy_forms/__init__.py
@@ -1 +1 @@
-__version__ = '1.8.1'
+__version__ = "1.8.1"
diff --git a/crispy_forms/base.py b/crispy_forms/base.py
index 7eba074ce..87c479aec 100644
--- a/crispy_forms/base.py
+++ b/crispy_forms/base.py
@@ -8,6 +8,7 @@ class KeepContext:
Layout objects should use `extra_context` to introduce context variables, never
touch context object themselves, that could introduce side effects.
"""
+
def __init__(self, context, keys):
self.context = context
self.keys = keys
diff --git a/crispy_forms/bootstrap.py b/crispy_forms/bootstrap.py
index 32ab86807..8a24fc8ea 100644
--- a/crispy_forms/bootstrap.py
+++ b/crispy_forms/bootstrap.py
@@ -15,48 +15,56 @@ def __init__(self, field, prepended_text=None, appended_text=None, *args, **kwar
self.field = field
self.appended_text = appended_text
self.prepended_text = prepended_text
- if 'active' in kwargs:
- self.active = kwargs.pop('active')
+ if "active" in kwargs:
+ self.active = kwargs.pop("active")
self.input_size = None
- css_class = kwargs.get('css_class', '')
- if 'input-lg' in css_class:
- self.input_size = 'input-lg'
- if 'input-sm' in css_class:
- self.input_size = 'input-sm'
+ css_class = kwargs.get("css_class", "")
+ if "input-lg" in css_class:
+ self.input_size = "input-lg"
+ if "input-sm" in css_class:
+ self.input_size = "input-sm"
super().__init__(field, *args, **kwargs)
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, extra_context=None, **kwargs):
extra_context = extra_context.copy() if extra_context is not None else {}
- extra_context.update({
- 'crispy_appended_text': self.appended_text,
- 'crispy_prepended_text': self.prepended_text,
- 'input_size': self.input_size,
- 'active': getattr(self, "active", False)
- })
- if hasattr(self, 'wrapper_class'):
- extra_context['wrapper_class'] = self.wrapper_class
+ extra_context.update(
+ {
+ "crispy_appended_text": self.appended_text,
+ "crispy_prepended_text": self.prepended_text,
+ "input_size": self.input_size,
+ "active": getattr(self, "active", False),
+ }
+ )
+ if hasattr(self, "wrapper_class"):
+ extra_context["wrapper_class"] = self.wrapper_class
template = self.get_template_name(template_pack)
return render_field(
- self.field, form, form_style, context,
- template=template, attrs=self.attrs,
- template_pack=template_pack, extra_context=extra_context, **kwargs
+ self.field,
+ form,
+ form_style,
+ context,
+ template=template,
+ attrs=self.attrs,
+ template_pack=template_pack,
+ extra_context=extra_context,
+ **kwargs,
)
class AppendedText(PrependedAppendedText):
def __init__(self, field, text, *args, **kwargs):
- kwargs.pop('appended_text', None)
- kwargs.pop('prepended_text', None)
+ kwargs.pop("appended_text", None)
+ kwargs.pop("prepended_text", None)
self.text = text
super().__init__(field, appended_text=text, **kwargs)
class PrependedText(PrependedAppendedText):
def __init__(self, field, text, *args, **kwargs):
- kwargs.pop('appended_text', None)
- kwargs.pop('prepended_text', None)
+ kwargs.pop("appended_text", None)
+ kwargs.pop("prepended_text", None)
self.text = text
super().__init__(field, prepended_text=text, **kwargs)
@@ -72,22 +80,20 @@ class FormActions(LayoutObject):
Submit('Save', 'Save', css_class='btn-primary')
)
"""
+
template = "%s/layout/formactions.html"
def __init__(self, *fields, **kwargs):
self.fields = list(fields)
- self.template = kwargs.pop('template', self.template)
+ self.template = kwargs.pop("template", self.template)
self.attrs = kwargs
- if 'css_class' in self.attrs:
- self.attrs['class'] = self.attrs.pop('css_class')
+ if "css_class" in self.attrs:
+ self.attrs["class"] = self.attrs.pop("css_class")
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
html = self.get_rendered_fields(form, form_style, context, template_pack, **kwargs)
template = self.get_template_name(template_pack)
- context.update({
- 'formactions': self,
- 'fields_output': html
- })
+ context.update({"formactions": self, "fields_output": html})
return render_to_string(template, context.flatten())
@@ -101,12 +107,12 @@ class InlineCheckboxes(Field):
InlineCheckboxes('field_name')
"""
+
template = "%s/layout/checkboxselectmultiple_inline.html"
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
return super().render(
- form, form_style, context, template_pack=template_pack,
- extra_context={'inline_class': 'inline'}
+ form, form_style, context, template_pack=template_pack, extra_context={"inline_class": "inline"}
)
@@ -116,45 +122,56 @@ class InlineRadios(Field):
InlineRadios('field_name')
"""
+
template = "%s/layout/radioselect_inline.html"
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
return super().render(
- form, form_style, context, template_pack=template_pack,
- extra_context={'inline_class': 'inline'}
+ form, form_style, context, template_pack=template_pack, extra_context={"inline_class": "inline"}
)
class FieldWithButtons(Div):
- template = '%s/layout/field_with_buttons.html'
- field_template = '%s/field.html'
+ template = "%s/layout/field_with_buttons.html"
+ field_template = "%s/field.html"
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, extra_context=None, **kwargs):
# We first render the buttons
field_template = self.field_template % template_pack
- buttons = ''.join(
+ buttons = "".join(
render_field(
- field, form, form_style, context,
- field_template, layout_object=self,
- template_pack=template_pack, **kwargs
- ) for field in self.fields[1:]
+ field,
+ form,
+ form_style,
+ context,
+ field_template,
+ layout_object=self,
+ template_pack=template_pack,
+ **kwargs,
+ )
+ for field in self.fields[1:]
)
- extra_context = {'div': self, 'buttons': buttons}
+ extra_context = {"div": self, "buttons": buttons}
template = self.get_template_name(template_pack)
if isinstance(self.fields[0], Field):
# FieldWithButtons(Field('field_name'), StrictButton("go"))
# We render the field passing its name and attributes
return render_field(
- self.fields[0][0], form, form_style, context,
- template, attrs=self.fields[0].attrs,
- template_pack=template_pack, extra_context=extra_context, **kwargs
+ self.fields[0][0],
+ form,
+ form_style,
+ context,
+ template,
+ attrs=self.fields[0].attrs,
+ template_pack=template_pack,
+ extra_context=extra_context,
+ **kwargs,
)
else:
return render_field(
- self.fields[0], form, form_style, context, template,
- extra_context=extra_context, **kwargs
+ self.fields[0], form, form_style, context, template, extra_context=extra_context, **kwargs
)
@@ -164,28 +181,29 @@ class StrictButton(TemplateNameMixin):
Button("button content", css_class="extra")
"""
- template = '%s/layout/button.html'
- field_classes = 'btn'
+
+ template = "%s/layout/button.html"
+ field_classes = "btn"
def __init__(self, content, **kwargs):
self.content = content
- self.template = kwargs.pop('template', self.template)
+ self.template = kwargs.pop("template", self.template)
- kwargs.setdefault('type', 'button')
+ kwargs.setdefault("type", "button")
# We turn css_id and css_class into id and class
- if 'css_id' in kwargs:
- kwargs['id'] = kwargs.pop('css_id')
- kwargs['class'] = self.field_classes
- if 'css_class' in kwargs:
- kwargs['class'] += " %s" % kwargs.pop('css_class')
+ if "css_id" in kwargs:
+ kwargs["id"] = kwargs.pop("css_id")
+ kwargs["class"] = self.field_classes
+ if "css_class" in kwargs:
+ kwargs["class"] += " %s" % kwargs.pop("css_class")
self.flat_attrs = flatatt(kwargs)
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
self.content = Template(str(self.content)).render(context)
template = self.get_template_name(template_pack)
- context.update({'button': self})
+ context.update({"button": self})
return render_to_string(template, context.flatten())
@@ -194,11 +212,12 @@ class Container(Div):
"""
Base class used for `Tab` and `AccordionGroup`, represents a basic container concept
"""
+
css_class = ""
def __init__(self, name, *fields, **kwargs):
super().__init__(*fields, **kwargs)
- self.template = kwargs.pop('template', self.template)
+ self.template = kwargs.pop("template", self.template)
self.name = name
self._active_originally_included = "active" in kwargs
self.active = kwargs.pop("active", False)
@@ -213,10 +232,10 @@ def __contains__(self, field_name):
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
if self.active:
- if 'active' not in self.css_class:
- self.css_class += ' active'
+ if "active" not in self.css_class:
+ self.css_class += " active"
else:
- self.css_class = self.css_class.replace('active', '')
+ self.css_class = self.css_class.replace("active", "")
return super().render(form, form_style, context, template_pack)
@@ -224,6 +243,7 @@ class ContainerHolder(Div):
"""
Base class used for `TabHolder` and `Accordion`, groups containers
"""
+
def first_container_with_errors(self, errors):
"""
Returns the first container with errors, otherwise returns None.
@@ -244,7 +264,7 @@ def open_target_group_for_form(self, form):
target = self.first_container_with_errors(form.errors.keys())
if target is None:
target = self.fields[0]
- if not getattr(target, '_active_originally_included', None):
+ if not getattr(target, "_active_originally_included", None):
target.active = True
return target
@@ -259,8 +279,9 @@ class Tab(Container):
Tab('tab_name', 'form_field_1', 'form_field_2', 'form_field_3')
"""
- css_class = 'tab-pane'
- link_template = '%s/layout/tab-link.html'
+
+ css_class = "tab-pane"
+ link_template = "%s/layout/tab-link.html"
def render_link(self, template_pack=TEMPLATE_PACK, **kwargs):
"""
@@ -268,7 +289,7 @@ def render_link(self, template_pack=TEMPLATE_PACK, **kwargs):
with active if needed.
"""
link_template = self.link_template % template_pack
- return render_to_string(link_template, {'link': self})
+ return render_to_string(link_template, {"link": self})
class TabHolder(ContainerHolder):
@@ -280,7 +301,8 @@ class TabHolder(ContainerHolder):
Tab('form_field_3')
)
"""
- template = '%s/layout/tab.html'
+
+ template = "%s/layout/tab.html"
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
for tab in self.fields:
@@ -289,13 +311,9 @@ def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwarg
# Open the group that should be open.
self.open_target_group_for_form(form)
content = self.get_rendered_fields(form, form_style, context, template_pack)
- links = ''.join(tab.render_link(template_pack) for tab in self.fields)
+ links = "".join(tab.render_link(template_pack) for tab in self.fields)
- context.update({
- 'tabs': self,
- 'links': links,
- 'content': content
- })
+ context.update({"tabs": self, "links": links, "content": content})
template = self.get_template_name(template_pack)
return render_to_string(template, context.flatten())
@@ -307,6 +325,7 @@ class AccordionGroup(Container):
AccordionGroup("group name", "form_field_1", "form_field_2")
"""
+
template = "%s/accordion-group.html"
data_parent = "" # accordion parent div id.
@@ -320,10 +339,11 @@ class Accordion(ContainerHolder):
AccordionGroup("another group name", "form_field")
)
"""
+
template = "%s/accordion.html"
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
- content = ''
+ content = ""
# accordion group needs the parent div id to set `data-parent` (I don't
# know why). This needs to be a unique id
@@ -335,12 +355,10 @@ def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwarg
for group in self.fields:
group.data_parent = self.css_id
- content += render_field(
- group, form, form_style, context, template_pack=template_pack, **kwargs
- )
+ content += render_field(group, form, form_style, context, template_pack=template_pack, **kwargs)
template = self.get_template_name(template_pack)
- context.update({'accordion': self, 'content': content})
+ context.update({"accordion": self, "content": content})
return render_to_string(template, context.flatten())
@@ -351,21 +369,22 @@ class Alert(Div):
Alert(content='Warning! Best check yo self, you're not looking too good.')
"""
+
template = "%s/layout/alert.html"
css_class = "alert"
def __init__(self, content, dismiss=True, block=False, **kwargs):
fields = []
if block:
- self.css_class += ' alert-block'
+ self.css_class += " alert-block"
Div.__init__(self, *fields, **kwargs)
- self.template = kwargs.pop('template', self.template)
+ self.template = kwargs.pop("template", self.template)
self.content = content
self.dismiss = dismiss
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
template = self.get_template_name(template_pack)
- context.update({'alert': self, 'content': self.content, 'dismiss': self.dismiss})
+ context.update({"alert": self, "content": self.content, "dismiss": self.dismiss})
return render_to_string(template, context.flatten())
@@ -378,10 +397,11 @@ class UneditableField(Field):
UneditableField('field_name', css_class="input-xlarge")
"""
+
template = "%s/layout/uneditable_input.html"
def __init__(self, field, *args, **kwargs):
- self.attrs = {'class': 'uneditable-input'}
+ self.attrs = {"class": "uneditable-input"}
super().__init__(field, *args, **kwargs)
diff --git a/crispy_forms/exceptions.py b/crispy_forms/exceptions.py
index 61b2382ca..24df311e2 100644
--- a/crispy_forms/exceptions.py
+++ b/crispy_forms/exceptions.py
@@ -8,6 +8,7 @@ class FormHelpersException(CrispyError):
We want to catch form helper errors as soon as possible because
debugging templatetags is never fun.
"""
+
pass
diff --git a/crispy_forms/helper.py b/crispy_forms/helper.py
index 720d1e648..726f1043d 100644
--- a/crispy_forms/helper.py
+++ b/crispy_forms/helper.py
@@ -31,8 +31,8 @@ def filter(self, *LayoutClasses, **kwargs):
Returns a LayoutSlice pointing to layout objects of type `LayoutClass`
"""
self._check_layout()
- max_level = kwargs.pop('max_level', 0)
- greedy = kwargs.pop('greedy', False)
+ max_level = kwargs.pop("max_level", 0)
+ greedy = kwargs.pop("greedy", False)
filtered_layout_objects = self.layout.get_layout_objects(LayoutClasses, max_level=max_level, greedy=greedy)
return LayoutSlice(self.layout, filtered_layout_objects)
@@ -184,13 +184,14 @@ def helper(self):
{% load crispy_forms_tags %}
{% crispy form %}
"""
- _form_method = 'post'
- _form_action = ''
- _form_style = 'default'
+
+ _form_method = "post"
+ _form_action = ""
+ _form_style = "default"
form = None
- form_id = ''
- form_class = ''
- form_group_wrapper_class = ''
+ form_id = ""
+ form_class = ""
+ form_group_wrapper_class = ""
layout = None
form_tag = True
form_error_title = None
@@ -207,8 +208,8 @@ def helper(self):
field_template = None
disable_csrf = False
use_custom_control = True
- label_class = ''
- field_class = ''
+ label_class = ""
+ field_class = ""
include_media = True
def __init__(self, form=None):
@@ -228,9 +229,11 @@ def form_method(self):
@form_method.setter
def form_method(self, method):
- if method.lower() not in ('get', 'post'):
- raise FormHelpersException('Only GET and POST are valid in the \
- form_method helper attribute')
+ if method.lower() not in ("get", "post"):
+ raise FormHelpersException(
+ "Only GET and POST are valid in the \
+ form_method helper attribute"
+ )
self._form_method = method.lower()
@@ -248,16 +251,18 @@ def form_action(self, action):
@property
def form_style(self):
if self._form_style == "default":
- return ''
+ return ""
if self._form_style == "inline":
- return 'inlineLabels'
+ return "inlineLabels"
@form_style.setter
def form_style(self, style):
- if style.lower() not in ('default', 'inline'):
- raise FormHelpersException('Only default and inline are valid in the \
- form_style helper attribute')
+ if style.lower() not in ("default", "inline"):
+ raise FormHelpersException(
+ "Only default and inline are valid in the \
+ form_style helper attribute"
+ )
self._form_style = style.lower()
@@ -293,12 +298,7 @@ def render_layout(self, form, context, template_pack=TEMPLATE_PACK):
form.crispy_field_template = self.field_template
# This renders the specified Layout strictly
- html = self.layout.render(
- form,
- self.form_style,
- context,
- template_pack=template_pack
- )
+ html = self.layout.render(form, self.form_style, context, template_pack=template_pack)
# Rendering some extra fields if specified
if self.render_unmentioned_fields or self.render_hidden_fields or self.render_required_fields:
@@ -306,17 +306,11 @@ def render_layout(self, form, context, template_pack=TEMPLATE_PACK):
left_fields_to_render = list_difference(fields, form.rendered_fields)
for field in left_fields_to_render:
if (
- self.render_unmentioned_fields or
- (self.render_hidden_fields and form.fields[field].widget.is_hidden) or
- (self.render_required_fields and form.fields[field].widget.is_required)
+ self.render_unmentioned_fields
+ or (self.render_hidden_fields and form.fields[field].widget.is_hidden)
+ or (self.render_required_fields and form.fields[field].widget.is_required)
):
- html += render_field(
- field,
- form,
- self.form_style,
- context,
- template_pack=template_pack
- )
+ html += render_field(field, form, self.form_style, context, template_pack=template_pack)
return mark_safe(html)
@@ -325,65 +319,68 @@ def get_attributes(self, template_pack=TEMPLATE_PACK):
Used by crispy_forms_tags to get helper attributes
"""
items = {
- 'disable_csrf': self.disable_csrf,
- 'error_text_inline': self.error_text_inline,
- 'field_class': self.field_class,
- 'field_template':
- self.field_template or '%s/field.html' % template_pack,
- 'form_method': self.form_method.strip(),
- 'form_show_errors': self.form_show_errors,
- 'form_show_labels': self.form_show_labels,
- 'form_style': self.form_style.strip(),
- 'form_tag': self.form_tag,
- 'help_text_inline': self.help_text_inline,
- 'html5_required': self.html5_required,
- 'include_media': self.include_media,
- 'label_class': self.label_class,
- 'use_custom_control': self.use_custom_control,
+ "disable_csrf": self.disable_csrf,
+ "error_text_inline": self.error_text_inline,
+ "field_class": self.field_class,
+ "field_template": self.field_template or "%s/field.html" % template_pack,
+ "form_method": self.form_method.strip(),
+ "form_show_errors": self.form_show_errors,
+ "form_show_labels": self.form_show_labels,
+ "form_style": self.form_style.strip(),
+ "form_tag": self.form_tag,
+ "help_text_inline": self.help_text_inline,
+ "html5_required": self.html5_required,
+ "include_media": self.include_media,
+ "label_class": self.label_class,
+ "use_custom_control": self.use_custom_control,
}
- if template_pack == 'bootstrap4':
- if 'form-horizontal' in self.form_class.split():
- bootstrap_size_match = re.findall(r'col-(xl|lg|md|sm)-(\d+)', self.label_class)
+ if template_pack == "bootstrap4":
+ if "form-horizontal" in self.form_class.split():
+ bootstrap_size_match = re.findall(r"col-(xl|lg|md|sm)-(\d+)", self.label_class)
if bootstrap_size_match:
- offset_pattern = 'offset-%s-%s'
- items['bootstrap_checkbox_offsets'] = [offset_pattern % m for m in bootstrap_size_match]
+ offset_pattern = "offset-%s-%s"
+ items["bootstrap_checkbox_offsets"] = [offset_pattern % m for m in bootstrap_size_match]
else:
- bootstrap_size_match = re.findall(r'col-(lg|md|sm|xs)-(\d+)', self.label_class)
+ bootstrap_size_match = re.findall(r"col-(lg|md|sm|xs)-(\d+)", self.label_class)
if bootstrap_size_match:
- offset_pattern = 'col-%s-offset-%s'
- items['bootstrap_checkbox_offsets'] = [offset_pattern % m for m in bootstrap_size_match]
+ offset_pattern = "col-%s-offset-%s"
+ items["bootstrap_checkbox_offsets"] = [offset_pattern % m for m in bootstrap_size_match]
- items['attrs'] = {}
+ items["attrs"] = {}
if self.attrs:
- items['attrs'] = self.attrs.copy()
+ items["attrs"] = self.attrs.copy()
if self.form_action:
- items['attrs']['action'] = self.form_action.strip()
+ items["attrs"]["action"] = self.form_action.strip()
if self.form_id:
- items['attrs']['id'] = self.form_id.strip()
+ items["attrs"]["id"] = self.form_id.strip()
if self.form_class:
# uni_form TEMPLATE PACK has a uniForm class by default
- if template_pack == 'uni_form':
- items['attrs']['class'] = "uniForm %s" % self.form_class.strip()
+ if template_pack == "uni_form":
+ items["attrs"]["class"] = "uniForm %s" % self.form_class.strip()
else:
- items['attrs']['class'] = self.form_class.strip()
+ items["attrs"]["class"] = self.form_class.strip()
else:
- if template_pack == 'uni_form':
- items['attrs']['class'] = self.attrs.get('class', '') + " uniForm"
+ if template_pack == "uni_form":
+ items["attrs"]["class"] = self.attrs.get("class", "") + " uniForm"
if self.form_group_wrapper_class:
- items['attrs']['form_group_wrapper_class'] = self.form_group_wrapper_class
+ items["attrs"]["form_group_wrapper_class"] = self.form_group_wrapper_class
- items['flat_attrs'] = flatatt(items['attrs'])
+ items["flat_attrs"] = flatatt(items["attrs"])
if self.inputs:
- items['inputs'] = self.inputs
+ items["inputs"] = self.inputs
if self.form_error_title:
- items['form_error_title'] = self.form_error_title.strip()
+ items["form_error_title"] = self.form_error_title.strip()
if self.formset_error_title:
- items['formset_error_title'] = self.formset_error_title.strip()
+ items["formset_error_title"] = self.formset_error_title.strip()
for attribute_name, value in self.__dict__.items():
- if attribute_name not in items and attribute_name not in ['layout', 'inputs'] and not attribute_name.startswith('_'):
+ if (
+ attribute_name not in items
+ and attribute_name not in ["layout", "inputs"]
+ and not attribute_name.startswith("_")
+ ):
items[attribute_name] = value
return items
diff --git a/crispy_forms/layout.py b/crispy_forms/layout.py
index b3c9dfe4e..5dfdb3519 100644
--- a/crispy_forms/layout.py
+++ b/crispy_forms/layout.py
@@ -6,9 +6,8 @@
class TemplateNameMixin:
-
def get_template_name(self, template_pack):
- if '%s' in self.template:
+ if "%s" in self.template:
template = self.template % template_pack
else:
template = self.template
@@ -35,7 +34,7 @@ def __getattr__(self, name):
having to declare them one by one
"""
# Check necessary for unpickling, see #107
- if 'fields' in self.__dict__ and hasattr(self.fields, name):
+ if "fields" in self.__dict__ and hasattr(self.fields, name):
return getattr(self.fields, name)
else:
return object.__getattribute__(self, name)
@@ -67,9 +66,9 @@ def get_layout_objects(self, *LayoutClasses, **kwargs):
:param greedy: Boolean that indicates whether to be greedy. If set, max_level
is skipped.
"""
- index = kwargs.pop('index', None)
- max_level = kwargs.pop('max_level', 0)
- greedy = kwargs.pop('greedy', False)
+ index = kwargs.pop("index", None)
+ max_level = kwargs.pop("max_level", 0)
+ greedy = kwargs.pop("greedy", False)
pointers = []
@@ -87,14 +86,14 @@ def get_layout_objects(self, *LayoutClasses, **kwargs):
# If it's a layout object and we haven't reached the max depth limit or greedy
# we recursive call
- if hasattr(layout_object, 'get_field_names') and (len(index) < max_level or greedy):
- new_kwargs = {'index': index + [i], 'max_level': max_level, 'greedy': greedy}
+ if hasattr(layout_object, "get_field_names") and (len(index) < max_level or greedy):
+ new_kwargs = {"index": index + [i], "max_level": max_level, "greedy": greedy}
pointers = pointers + layout_object.get_layout_objects(*LayoutClasses, **new_kwargs)
return pointers
def get_rendered_fields(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
- return ''.join(
+ return "".join(
render_field(field, form, form_style, context, template_pack=template_pack, **kwargs)
for field in self.fields
)
@@ -128,6 +127,7 @@ class Layout(LayoutObject):
),
)
"""
+
def __init__(self, *fields):
self.fields = list(fields)
@@ -149,19 +149,20 @@ class ButtonHolder(LayoutObject):
Submit('Save', 'Save')
)
"""
+
template = "%s/layout/buttonholder.html"
def __init__(self, *fields, **kwargs):
self.fields = list(fields)
- self.css_class = kwargs.get('css_class', None)
- self.css_id = kwargs.get('css_id', None)
- self.template = kwargs.get('template', self.template)
+ self.css_class = kwargs.get("css_class", None)
+ self.css_id = kwargs.get("css_id", None)
+ self.template = kwargs.get("template", self.template)
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
html = self.get_rendered_fields(form, form_style, context, template_pack, **kwargs)
template = self.get_template_name(template_pack)
- context.update({'buttonholder': self, 'fields_output': html})
+ context.update({"buttonholder": self, "fields_output": html})
return render_to_string(template, context.flatten())
@@ -170,18 +171,19 @@ class BaseInput(TemplateNameMixin):
"""
A base class to reduce the amount of code in the Input classes.
"""
+
template = "%s/layout/baseinput.html"
def __init__(self, name, value, **kwargs):
self.name = name
self.value = value
- self.id = kwargs.pop('css_id', '')
+ self.id = kwargs.pop("css_id", "")
self.attrs = {}
- if 'css_class' in kwargs:
- self.field_classes += ' %s' % kwargs.pop('css_class')
+ if "css_class" in kwargs:
+ self.field_classes += " %s" % kwargs.pop("css_class")
- self.template = kwargs.pop('template', self.template)
+ self.template = kwargs.pop("template", self.template)
self.flat_attrs = flatatt(kwargs)
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
@@ -191,7 +193,7 @@ def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwarg
"""
self.value = Template(str(self.value)).render(context)
template = self.get_template_name(template_pack)
- context.update({'input': self})
+ context.update({"input": self})
return render_to_string(template, context.flatten())
@@ -204,10 +206,11 @@ class Submit(BaseInput):
.. note:: The first argument is also slugified and turned into the id for the submit button.
"""
- input_type = 'submit'
+
+ input_type = "submit"
def __init__(self, *args, **kwargs):
- self.field_classes = 'submit submitButton' if get_template_pack() == 'uni_form' else 'btn btn-primary'
+ self.field_classes = "submit submitButton" if get_template_pack() == "uni_form" else "btn btn-primary"
super().__init__(*args, **kwargs)
@@ -219,10 +222,11 @@ class Button(BaseInput):
.. note:: The first argument is also slugified and turned into the id for the button.
"""
- input_type = 'button'
+
+ input_type = "button"
def __init__(self, *args, **kwargs):
- self.field_classes = 'button' if get_template_pack() == 'uni_form' else 'btn'
+ self.field_classes = "button" if get_template_pack() == "uni_form" else "btn"
super().__init__(*args, **kwargs)
@@ -230,8 +234,9 @@ class Hidden(BaseInput):
"""
Used to create a Hidden input descriptor for the {% crispy %} template tag.
"""
- input_type = 'hidden'
- field_classes = 'hidden'
+
+ input_type = "hidden"
+ field_classes = "hidden"
class Reset(BaseInput):
@@ -242,10 +247,11 @@ class Reset(BaseInput):
.. note:: The first argument is also slugified and turned into the id for the reset.
"""
- input_type = 'reset'
+
+ input_type = "reset"
def __init__(self, *args, **kwargs):
- self.field_classes = 'reset resetButton' if get_template_pack() == 'uni_form' else 'btn btn-inverse'
+ self.field_classes = "reset resetButton" if get_template_pack() == "uni_form" else "btn btn-inverse"
super().__init__(*args, **kwargs)
@@ -268,64 +274,68 @@ class Fieldset(LayoutObject):
'form_field_2'
)
"""
+
template = "%s/layout/fieldset.html"
def __init__(self, legend, *fields, **kwargs):
self.fields = list(fields)
self.legend = legend
- self.css_class = kwargs.pop('css_class', '')
- self.css_id = kwargs.pop('css_id', None)
- self.template = kwargs.pop('template', self.template)
+ self.css_class = kwargs.pop("css_class", "")
+ self.css_id = kwargs.pop("css_id", None)
+ self.template = kwargs.pop("template", self.template)
self.flat_attrs = flatatt(kwargs)
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
fields = self.get_rendered_fields(form, form_style, context, template_pack, **kwargs)
- legend = ''
+ legend = ""
if self.legend:
- legend = '%s' % Template(str(self.legend)).render(context)
+ legend = "%s" % Template(str(self.legend)).render(context)
template = self.get_template_name(template_pack)
return render_to_string(
- template,
- {'fieldset': self, 'legend': legend, 'fields': fields, 'form_style': form_style}
+ template, {"fieldset": self, "legend": legend, "fields": fields, "form_style": form_style}
)
class MultiField(LayoutObject):
""" MultiField container. Renders to a MultiField
"""
+
template = "%s/layout/multifield.html"
field_template = "%s/multifield.html"
def __init__(self, label, *fields, **kwargs):
self.fields = list(fields)
self.label_html = label
- self.label_class = kwargs.pop('label_class', 'blockLabel')
- self.css_class = kwargs.pop('css_class', 'ctrlHolder')
- self.css_id = kwargs.pop('css_id', None)
- self.help_text = kwargs.pop('help_text', None)
- self.template = kwargs.pop('template', self.template)
- self.field_template = kwargs.pop('field_template', self.field_template)
+ self.label_class = kwargs.pop("label_class", "blockLabel")
+ self.css_class = kwargs.pop("css_class", "ctrlHolder")
+ self.css_id = kwargs.pop("css_id", None)
+ self.help_text = kwargs.pop("help_text", None)
+ self.template = kwargs.pop("template", self.template)
+ self.field_template = kwargs.pop("field_template", self.field_template)
self.flat_attrs = flatatt(kwargs)
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
# If a field within MultiField contains errors
- if context['form_show_errors']:
+ if context["form_show_errors"]:
for field in map(lambda pointer: pointer[1], self.get_field_names()):
if field in form.errors:
self.css_class += " error"
field_template = self.field_template % template_pack
fields_output = self.get_rendered_fields(
- form, form_style, context, template_pack, template=field_template,
- labelclass=self.label_class, layout_object=self, **kwargs
+ form,
+ form_style,
+ context,
+ template_pack,
+ template=field_template,
+ labelclass=self.label_class,
+ layout_object=self,
+ **kwargs,
)
template = self.get_template_name(template_pack)
- context.update({
- 'multifield': self,
- 'fields_output': fields_output
- })
+ context.update({"multifield": self, "fields_output": fields_output})
return render_to_string(template, context.flatten())
@@ -338,25 +348,26 @@ class Div(LayoutObject):
Div('form_field_1', 'form_field_2', css_id='div-example', css_class='divs')
"""
+
template = "%s/layout/div.html"
def __init__(self, *fields, **kwargs):
self.fields = list(fields)
- if hasattr(self, 'css_class') and 'css_class' in kwargs:
- self.css_class += ' %s' % kwargs.pop('css_class')
- if not hasattr(self, 'css_class'):
- self.css_class = kwargs.pop('css_class', None)
+ if hasattr(self, "css_class") and "css_class" in kwargs:
+ self.css_class += " %s" % kwargs.pop("css_class")
+ if not hasattr(self, "css_class"):
+ self.css_class = kwargs.pop("css_class", None)
- self.css_id = kwargs.pop('css_id', '')
- self.template = kwargs.pop('template', self.template)
+ self.css_id = kwargs.pop("css_id", "")
+ self.template = kwargs.pop("template", self.template)
self.flat_attrs = flatatt(kwargs)
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
fields = self.get_rendered_fields(form, form_style, context, template_pack, **kwargs)
template = self.get_template_name(template_pack)
- return render_to_string(template, {'div': self, 'fields': fields})
+ return render_to_string(template, {"div": self, "fields": fields})
class Row(Div):
@@ -365,6 +376,7 @@ class Row(Div):
Row('form_field_1', 'form_field_2', 'form_field_3')
"""
+
template = "%s/layout/row.html"
@@ -379,6 +391,7 @@ class Column(Div):
Column('form_field_1', 'form_field_2', css_class='col-xs-6',)
"""
+
template = "%s/layout/column.html"
@@ -409,41 +422,47 @@ class Field(LayoutObject):
Field('field_name', style="color: #333;", css_class="whatever", id="field_name")
"""
+
template = "%s/field.html"
def __init__(self, *args, **kwargs):
self.fields = list(args)
- if not hasattr(self, 'attrs'):
+ if not hasattr(self, "attrs"):
self.attrs = {}
else:
# Make sure shared state is not edited.
self.attrs = self.attrs.copy()
- if 'css_class' in kwargs:
- if 'class' in self.attrs:
- self.attrs['class'] += " %s" % kwargs.pop('css_class')
+ if "css_class" in kwargs:
+ if "class" in self.attrs:
+ self.attrs["class"] += " %s" % kwargs.pop("css_class")
else:
- self.attrs['class'] = kwargs.pop('css_class')
+ self.attrs["class"] = kwargs.pop("css_class")
- self.wrapper_class = kwargs.pop('wrapper_class', None)
- self.template = kwargs.pop('template', self.template)
+ self.wrapper_class = kwargs.pop("wrapper_class", None)
+ self.template = kwargs.pop("template", self.template)
# We use kwargs as HTML attributes, turning data_id='test' into data-id='test'
- self.attrs.update({k.replace('_', '-'): conditional_escape(v) for k, v in kwargs.items()})
+ self.attrs.update({k.replace("_", "-"): conditional_escape(v) for k, v in kwargs.items()})
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, extra_context=None, **kwargs):
if extra_context is None:
extra_context = {}
- if hasattr(self, 'wrapper_class'):
- extra_context['wrapper_class'] = self.wrapper_class
+ if hasattr(self, "wrapper_class"):
+ extra_context["wrapper_class"] = self.wrapper_class
template = self.get_template_name(template_pack)
return self.get_rendered_fields(
- form, form_style, context, template_pack,
- template=template, attrs=self.attrs, extra_context=extra_context,
- **kwargs
+ form,
+ form_style,
+ context,
+ template_pack,
+ template=template,
+ attrs=self.attrs,
+ extra_context=extra_context,
+ **kwargs,
)
@@ -464,8 +483,9 @@ class MultiWidgetField(Field):
.. note:: To override widget's css class use ``class`` not ``css_class``.
"""
+
def __init__(self, *args, **kwargs):
self.fields = list(args)
- self.attrs = kwargs.pop('attrs', {})
- self.template = kwargs.pop('template', self.template)
- self.wrapper_class = kwargs.pop('wrapper_class', None)
+ self.attrs = kwargs.pop("attrs", {})
+ self.template = kwargs.pop("template", self.template)
+ self.wrapper_class = kwargs.pop("wrapper_class", None)
diff --git a/crispy_forms/layout_slice.py b/crispy_forms/layout_slice.py
index 38539142e..43d761d92 100644
--- a/crispy_forms/layout_slice.py
+++ b/crispy_forms/layout_slice.py
@@ -64,18 +64,19 @@ def pre_map(self, function):
except IndexError:
# We could avoid this exception, recalculating pointers.
# However this case is most of the time an undesired behavior
- raise DynamicError("Trying to wrap a field within an already wrapped field, \
- recheck your filter or layout")
+ raise DynamicError(
+ "Trying to wrap a field within an already wrapped field, \
+ recheck your filter or layout"
+ )
def wrap(self, LayoutClass, *args, **kwargs):
"""
Wraps every layout object pointed in `self.slice` under a `LayoutClass` instance with
`args` and `kwargs` passed.
"""
+
def wrap_object(layout_object, j):
- layout_object.fields[j] = self.wrapped_object(
- LayoutClass, layout_object.fields[j], *args, **kwargs
- )
+ layout_object.fields[j] = self.wrapped_object(LayoutClass, layout_object.fields[j], *args, **kwargs)
self.pre_map(wrap_object)
@@ -85,11 +86,10 @@ def wrap_once(self, LayoutClass, *args, **kwargs):
`args` and `kwargs` passed, unless layout object's parent is already a subclass of
`LayoutClass`.
"""
+
def wrap_object_once(layout_object, j):
if not isinstance(layout_object, LayoutClass):
- layout_object.fields[j] = self.wrapped_object(
- LayoutClass, layout_object.fields[j], *args, **kwargs
- )
+ layout_object.fields[j] = self.wrapped_object(LayoutClass, layout_object.fields[j], *args, **kwargs)
self.pre_map(wrap_object_once)
@@ -133,10 +133,7 @@ def map(self, function):
layout_object = layout_object.fields[i]
# If update_attrs is applied to a string, we call to its wrapping layout object
- if (
- function.__name__ == 'update_attrs'
- and isinstance(layout_object, str)
- ):
+ if function.__name__ == "update_attrs" and isinstance(layout_object, str):
function(previous_layout_object)
else:
function(layout_object)
@@ -145,14 +142,15 @@ def update_attributes(self, **original_kwargs):
"""
Updates attributes of every layout object pointed in `self.slice` using kwargs
"""
+
def update_attrs(layout_object):
kwargs = original_kwargs.copy()
- if hasattr(layout_object, 'attrs'):
- if 'css_class' in kwargs:
- if 'class' in layout_object.attrs:
- layout_object.attrs['class'] += " %s" % kwargs.pop('css_class')
+ if hasattr(layout_object, "attrs"):
+ if "css_class" in kwargs:
+ if "class" in layout_object.attrs:
+ layout_object.attrs["class"] += " %s" % kwargs.pop("css_class")
else:
- layout_object.attrs['class'] = kwargs.pop('css_class')
+ layout_object.attrs["class"] = kwargs.pop("css_class")
layout_object.attrs.update(kwargs)
self.map(update_attrs)
diff --git a/crispy_forms/templatetags/crispy_forms_field.py b/crispy_forms/templatetags/crispy_forms_field.py
index 73bf54c55..c36161722 100644
--- a/crispy_forms/templatetags/crispy_forms_field.py
+++ b/crispy_forms/templatetags/crispy_forms_field.py
@@ -52,7 +52,7 @@ def classes(field):
"""
Returns CSS classes of a field
"""
- return field.widget.attrs.get('class', None)
+ return field.widget.attrs.get("class", None)
@register.filter
@@ -73,7 +73,7 @@ class CrispyFieldNode(template.Node):
def __init__(self, field, attrs):
self.field = field
self.attrs = attrs
- self.html5_required = 'html5_required'
+ self.html5_required = "html5_required"
def render(self, context):
# Nodes are not threadsafe so we must store and look up our instance
@@ -82,7 +82,7 @@ def render(self, context):
context.render_context[self] = (
template.Variable(self.field),
self.attrs,
- template.Variable(self.html5_required)
+ template.Variable(self.html5_required),
)
field, attrs, html5_required = context.render_context[self]
@@ -93,26 +93,26 @@ def render(self, context):
html5_required = False
# If template pack has been overridden in FormHelper we can pick it from context
- template_pack = context.get('template_pack', TEMPLATE_PACK)
+ template_pack = context.get("template_pack", TEMPLATE_PACK)
# There are special django widgets that wrap actual widgets,
# such as forms.widgets.MultiWidget, admin.widgets.RelatedFieldWidgetWrapper
- widgets = getattr(field.field.widget, 'widgets', [getattr(field.field.widget, 'widget', field.field.widget)])
+ widgets = getattr(field.field.widget, "widgets", [getattr(field.field.widget, "widget", field.field.widget)])
if isinstance(attrs, dict):
attrs = [attrs] * len(widgets)
converters = {
- 'textinput': 'textinput textInput',
- 'fileinput': 'fileinput fileUpload',
- 'passwordinput': 'textinput textInput',
+ "textinput": "textinput textInput",
+ "fileinput": "fileinput fileUpload",
+ "passwordinput": "textinput textInput",
}
- converters.update(getattr(settings, 'CRISPY_CLASS_CONVERTERS', {}))
+ converters.update(getattr(settings, "CRISPY_CLASS_CONVERTERS", {}))
for widget, attr in zip(widgets, attrs):
class_name = widget.__class__.__name__.lower()
class_name = converters.get(class_name, class_name)
- css_class = widget.attrs.get('class', '')
+ css_class = widget.attrs.get("class", "")
if css_class:
if css_class.find(class_name) == -1:
css_class += " %s" % class_name
@@ -120,32 +120,29 @@ def render(self, context):
css_class = class_name
if (
- template_pack == 'bootstrap3'
+ template_pack == "bootstrap3"
and not is_checkbox(field)
and not is_file(field)
and not is_multivalue(field)
):
- css_class += ' form-control'
+ css_class += " form-control"
if field.errors:
- css_class += ' form-control-danger'
+ css_class += " form-control-danger"
- if (
- template_pack == 'bootstrap4'
- and not is_multivalue(field)
- ):
+ if template_pack == "bootstrap4" and not is_multivalue(field):
if not is_checkbox(field):
- css_class += ' form-control'
+ css_class += " form-control"
if is_file(field):
- css_class += '-file'
+ css_class += "-file"
if field.errors:
- css_class += ' is-invalid'
+ css_class += " is-invalid"
- widget.attrs['class'] = css_class
+ widget.attrs["class"] = css_class
# HTML5 required attribute
- if html5_required and field.field.required and 'required' not in widget.attrs:
- if field.field.widget.__class__.__name__ != 'RadioSelect':
- widget.attrs['required'] = 'required'
+ if html5_required and field.field.required and "required" not in widget.attrs:
+ if field.field.widget.__class__.__name__ != "RadioSelect":
+ widget.attrs["required"] = "required"
for attribute_name, attribute in attr.items():
attribute_name = template.Variable(attribute_name).resolve(context)
@@ -188,14 +185,10 @@ def crispy_addon(field, append="", prepend="", form_show_labels=True):
{% crispy_addon form.my_field append=".00" %}
"""
if field:
- context = Context({
- 'field': field,
- 'form_show_errors': True,
- 'form_show_labels': form_show_labels,
- })
- template = loader.get_template('%s/layout/prepended_appended_text.html' % get_template_pack())
- context['crispy_prepended_text'] = prepend
- context['crispy_appended_text'] = append
+ context = Context({"field": field, "form_show_errors": True, "form_show_labels": form_show_labels,})
+ template = loader.get_template("%s/layout/prepended_appended_text.html" % get_template_pack())
+ context["crispy_prepended_text"] = prepend
+ context["crispy_appended_text"] = append
if not prepend and not append:
raise TypeError("Expected a prepend and/or append argument")
diff --git a/crispy_forms/templatetags/crispy_forms_filters.py b/crispy_forms/templatetags/crispy_forms_filters.py
index dccb0eb17..e99e7d04b 100644
--- a/crispy_forms/templatetags/crispy_forms_filters.py
+++ b/crispy_forms/templatetags/crispy_forms_filters.py
@@ -13,18 +13,18 @@
@lru_cache()
def uni_formset_template(template_pack=TEMPLATE_PACK):
- return get_template('%s/uni_formset.html' % template_pack)
+ return get_template("%s/uni_formset.html" % template_pack)
@lru_cache()
def uni_form_template(template_pack=TEMPLATE_PACK):
- return get_template('%s/uni_form.html' % template_pack)
+ return get_template("%s/uni_form.html" % template_pack)
register = template.Library()
-@register.filter(name='crispy')
+@register.filter(name="crispy")
def as_crispy_form(form, template_pack=TEMPLATE_PACK, label_class="", field_class=""):
"""
The original and still very useful way to generate a div elegant form/formset::
@@ -44,24 +44,26 @@ def as_crispy_form(form, template_pack=TEMPLATE_PACK, label_class="", field_clas
{{ myform|label_class:"col-lg-2",field_class:"col-lg-8" }}
"""
- c = Context({
- 'field_class': field_class,
- 'field_template': '%s/field.html' % template_pack,
- 'form_show_errors': True,
- 'form_show_labels': True,
- 'label_class': label_class,
- }).flatten()
+ c = Context(
+ {
+ "field_class": field_class,
+ "field_template": "%s/field.html" % template_pack,
+ "form_show_errors": True,
+ "form_show_labels": True,
+ "label_class": label_class,
+ }
+ ).flatten()
if isinstance(form, BaseFormSet):
template = uni_formset_template(template_pack)
- c['formset'] = form
+ c["formset"] = form
else:
template = uni_form_template(template_pack)
- c['form'] = form
+ c["form"] = form
return template.render(c)
-@register.filter(name='as_crispy_errors')
+@register.filter(name="as_crispy_errors")
def as_crispy_errors(form, template_pack=TEMPLATE_PACK):
"""
Renders only form errors the same way as django-crispy-forms::
@@ -74,16 +76,16 @@ def as_crispy_errors(form, template_pack=TEMPLATE_PACK):
{{ form|as_crispy_errors:"bootstrap" }}
"""
if isinstance(form, BaseFormSet):
- template = get_template('%s/errors_formset.html' % template_pack)
- c = Context({'formset': form}).flatten()
+ template = get_template("%s/errors_formset.html" % template_pack)
+ c = Context({"formset": form}).flatten()
else:
- template = get_template('%s/errors.html' % template_pack)
- c = Context({'form': form}).flatten()
+ template = get_template("%s/errors.html" % template_pack)
+ c = Context({"form": form}).flatten()
return template.render(c)
-@register.filter(name='as_crispy_field')
+@register.filter(name="as_crispy_field")
def as_crispy_field(field, template_pack=TEMPLATE_PACK, label_class="", field_class=""):
"""
Renders a form field like a django-crispy-forms field::
@@ -96,29 +98,29 @@ def as_crispy_field(field, template_pack=TEMPLATE_PACK, label_class="", field_cl
{{ form.field|as_crispy_field:"bootstrap" }}
"""
if not isinstance(field, boundfield.BoundField) and settings.DEBUG:
- raise CrispyError('|as_crispy_field got passed an invalid or inexistent field')
+ raise CrispyError("|as_crispy_field got passed an invalid or inexistent field")
attributes = {
- 'field': field,
- 'form_show_errors': True,
- 'form_show_labels': True,
- 'label_class': label_class,
- 'field_class': field_class,
+ "field": field,
+ "form_show_errors": True,
+ "form_show_labels": True,
+ "label_class": label_class,
+ "field_class": field_class,
}
- helper = getattr(field.form, 'helper', None)
+ helper = getattr(field.form, "helper", None)
template_path = None
if helper is not None:
attributes.update(helper.get_attributes(template_pack))
template_path = helper.field_template
if not template_path:
- template_path = '%s/field.html' % template_pack
+ template_path = "%s/field.html" % template_pack
template = get_template(template_path)
c = Context(attributes).flatten()
return template.render(c)
-@register.filter(name='flatatt')
+@register.filter(name="flatatt")
def flatatt_filter(attrs):
return mark_safe(flatatt(attrs))
diff --git a/crispy_forms/templatetags/crispy_forms_tags.py b/crispy_forms/templatetags/crispy_forms_tags.py
index dc0e3db2a..60f523364 100644
--- a/crispy_forms/templatetags/crispy_forms_tags.py
+++ b/crispy_forms/templatetags/crispy_forms_tags.py
@@ -25,6 +25,7 @@ class ForLoopSimulator:
Fieldset("Item {{ forloop.counter }}", [...])
HTML("{% if forloop.first %}First form text{% endif %}"
"""
+
def __init__(self, formset):
self.len_values = len(formset.forms)
@@ -36,7 +37,7 @@ def __init__(self, formset):
self.revcounter0 = self.len_values - 1
# Boolean values designating first and last times through loop.
self.first = True
- self.last = (0 == self.len_values - 1)
+ self.last = 0 == self.len_values - 1
def iterate(self):
"""
@@ -47,7 +48,7 @@ def iterate(self):
self.revcounter -= 1
self.revcounter0 -= 1
self.first = False
- self.last = (self.revcounter0 == self.len_values - 1)
+ self.last = self.revcounter0 == self.len_values - 1
class BasicNode(template.Node):
@@ -58,6 +59,7 @@ class BasicNode(template.Node):
both the form object and parses out the helper string into attributes
that templates can easily handle.
"""
+
def __init__(self, form, helper, template_pack=None):
self.form = form
if helper is not None:
@@ -82,7 +84,7 @@ def get_render(self, context):
if self not in context.render_context:
context.render_context[self] = (
template.Variable(self.form),
- template.Variable(self.helper) if self.helper else None
+ template.Variable(self.helper) if self.helper else None,
)
form, helper = context.render_context[self]
@@ -92,7 +94,7 @@ def get_render(self, context):
else:
# If the user names the helper within the form `helper` (standard), we use it
# This allows us to have simplified tag syntax: {% crispy form %}
- helper = FormHelper() if not hasattr(actual_form, 'helper') else actual_form.helper
+ helper = FormHelper() if not hasattr(actual_form, "helper") else actual_form.helper
# use template_pack from helper, if defined
try:
@@ -107,27 +109,29 @@ def get_render(self, context):
is_formset = isinstance(actual_form, BaseFormSet)
response_dict = self.get_response_dict(helper, context, is_formset)
node_context = context.__copy__()
- node_context.update({'is_bound': actual_form.is_bound})
+ node_context.update({"is_bound": actual_form.is_bound})
node_context.update(response_dict)
final_context = node_context.__copy__()
# If we have a helper's layout we use it, for the form or the formset's forms
if helper and helper.layout:
if not is_formset:
- actual_form.form_html = helper.render_layout(actual_form, node_context, template_pack=self.template_pack)
+ actual_form.form_html = helper.render_layout(
+ actual_form, node_context, template_pack=self.template_pack
+ )
else:
forloop = ForLoopSimulator(actual_form)
helper.render_hidden_fields = True
for form in actual_form:
- node_context.update({'forloop': forloop})
- node_context.update({'formset_form': form})
+ node_context.update({"forloop": forloop})
+ node_context.update({"formset_form": form})
form.form_html = helper.render_layout(form, node_context, template_pack=self.template_pack)
forloop.iterate()
if is_formset:
- final_context['formset'] = actual_form
+ final_context["formset"] = actual_form
else:
- final_context['form'] = actual_form
+ final_context["form"] = actual_form
return final_context
@@ -139,7 +143,7 @@ def get_response_dict(self, helper, context, is_formset):
:param is_formset: Boolean value. If set to True, indicates we are working with a formset.
"""
if not isinstance(helper, FormHelper):
- raise TypeError('helper object provided to {% crispy %} tag must be a crispy.helper.FormHelper object.')
+ raise TypeError("helper object provided to {% crispy %} tag must be a crispy.helper.FormHelper object.")
attrs = helper.get_attributes(template_pack=self.template_pack)
form_type = "form"
@@ -148,29 +152,29 @@ def get_response_dict(self, helper, context, is_formset):
# We take form/formset parameters from attrs if they are set, otherwise we use defaults
response_dict = {
- '%s_action' % form_type: attrs['attrs'].get('action', ''),
- '%s_attrs' % form_type: attrs.get('attrs', ''),
- '%s_class' % form_type: attrs['attrs'].get('class', ''),
- '%s_id' % form_type: attrs['attrs'].get('id', ''),
- '%s_method' % form_type: attrs.get('form_method', 'post'),
- '%s_style' % form_type: attrs.get('form_style', None),
- '%s_tag' % form_type: attrs.get('form_tag', True),
- 'disable_csrf': attrs.get('disable_csrf', False),
- 'error_text_inline': attrs.get('error_text_inline', True),
- 'field_class': attrs.get('field_class', ''),
- 'field_template': attrs.get('field_template', ''),
- 'flat_attrs': attrs.get('flat_attrs', ''),
- 'form_error_title': attrs.get('form_error_title', None),
- 'form_show_errors': attrs.get('form_show_errors', True),
- 'form_show_labels': attrs.get('form_show_labels', True),
- 'formset_error_title': attrs.get('formset_error_title', None),
- 'help_text_inline': attrs.get('help_text_inline', False),
- 'html5_required': attrs.get('html5_required', False),
- 'include_media': attrs.get('include_media', True),
- 'inputs': attrs.get('inputs', []),
- 'is_formset': is_formset,
- 'label_class': attrs.get('label_class', ''),
- 'template_pack': self.template_pack,
+ "%s_action" % form_type: attrs["attrs"].get("action", ""),
+ "%s_attrs" % form_type: attrs.get("attrs", ""),
+ "%s_class" % form_type: attrs["attrs"].get("class", ""),
+ "%s_id" % form_type: attrs["attrs"].get("id", ""),
+ "%s_method" % form_type: attrs.get("form_method", "post"),
+ "%s_style" % form_type: attrs.get("form_style", None),
+ "%s_tag" % form_type: attrs.get("form_tag", True),
+ "disable_csrf": attrs.get("disable_csrf", False),
+ "error_text_inline": attrs.get("error_text_inline", True),
+ "field_class": attrs.get("field_class", ""),
+ "field_template": attrs.get("field_template", ""),
+ "flat_attrs": attrs.get("flat_attrs", ""),
+ "form_error_title": attrs.get("form_error_title", None),
+ "form_show_errors": attrs.get("form_show_errors", True),
+ "form_show_labels": attrs.get("form_show_labels", True),
+ "formset_error_title": attrs.get("formset_error_title", None),
+ "help_text_inline": attrs.get("help_text_inline", False),
+ "html5_required": attrs.get("html5_required", False),
+ "include_media": attrs.get("include_media", True),
+ "inputs": attrs.get("inputs", []),
+ "is_formset": is_formset,
+ "label_class": attrs.get("label_class", ""),
+ "template_pack": self.template_pack,
}
# Handles custom attributes added to helpers
@@ -178,30 +182,30 @@ def get_response_dict(self, helper, context, is_formset):
if attribute_name not in response_dict:
response_dict[attribute_name] = value
- if 'csrf_token' in context:
- response_dict['csrf_token'] = context['csrf_token']
+ if "csrf_token" in context:
+ response_dict["csrf_token"] = context["csrf_token"]
return response_dict
@lru_cache()
def whole_uni_formset_template(template_pack=TEMPLATE_PACK):
- return get_template('%s/whole_uni_formset.html' % template_pack)
+ return get_template("%s/whole_uni_formset.html" % template_pack)
@lru_cache()
def whole_uni_form_template(template_pack=TEMPLATE_PACK):
- return get_template('%s/whole_uni_form.html' % template_pack)
+ return get_template("%s/whole_uni_form.html" % template_pack)
class CrispyFormNode(BasicNode):
def render(self, context):
c = self.get_render(context).flatten()
- if self.actual_helper is not None and getattr(self.actual_helper, 'template', False):
+ if self.actual_helper is not None and getattr(self.actual_helper, "template", False):
template = get_template(self.actual_helper.template)
else:
- if c['is_formset']:
+ if c["is_formset"]:
template = whole_uni_formset_template(self.template_pack)
else:
template = whole_uni_form_template(self.template_pack)
@@ -250,25 +254,18 @@ def do_uni_form(parser, token):
pass
# {% crispy form 'bootstrap' %}
- if (
- helper is not None and
- isinstance(helper, str) and
- ("'" in helper or '"' in helper)
- ):
+ if helper is not None and isinstance(helper, str) and ("'" in helper or '"' in helper):
template_pack = helper
helper = None
if template_pack is not None:
template_pack = template_pack[1:-1]
ALLOWED_TEMPLATE_PACKS = getattr(
- settings,
- 'CRISPY_ALLOWED_TEMPLATE_PACKS',
- ('bootstrap', 'uni_form', 'bootstrap3', 'bootstrap4')
+ settings, "CRISPY_ALLOWED_TEMPLATE_PACKS", ("bootstrap", "uni_form", "bootstrap3", "bootstrap4")
)
if template_pack not in ALLOWED_TEMPLATE_PACKS:
raise template.TemplateSyntaxError(
- "crispy tag's template_pack argument should be in %s" %
- str(ALLOWED_TEMPLATE_PACKS)
+ "crispy tag's template_pack argument should be in %s" % str(ALLOWED_TEMPLATE_PACKS)
)
return CrispyFormNode(form, helper, template_pack=template_pack)
diff --git a/crispy_forms/templatetags/crispy_forms_utils.py b/crispy_forms/templatetags/crispy_forms_utils.py
index 0ea7f1dd6..2b206a323 100644
--- a/crispy_forms/templatetags/crispy_forms_utils.py
+++ b/crispy_forms/templatetags/crispy_forms_utils.py
@@ -9,8 +9,8 @@
@keep_lazy(str)
def remove_spaces(value):
- html = re.sub(r'>\s{3,}<', '> <', force_str(value))
- return re.sub(r'/><', r'/> <', force_str(html))
+ html = re.sub(r">\s{3,}<", "> <", force_str(value))
+ return re.sub(r"/><", r"/> <", force_str(html))
class SpecialSpacelessNode(template.Node):
@@ -28,7 +28,7 @@ def specialspaceless(parser, token):
after buttons an inputs, necessary for Bootstrap to place them
correctly in the layout.
"""
- nodelist = parser.parse(('endspecialspaceless',))
+ nodelist = parser.parse(("endspecialspaceless",))
parser.delete_first_token()
return SpecialSpacelessNode(nodelist)
diff --git a/crispy_forms/tests/conftest.py b/crispy_forms/tests/conftest.py
index 594df5568..cdd8e7a1e 100644
--- a/crispy_forms/tests/conftest.py
+++ b/crispy_forms/tests/conftest.py
@@ -2,41 +2,34 @@
from crispy_forms.layout import HTML, Div, Field, Fieldset, Layout, Submit
-only_uni_form = pytest.mark.only('uni_form')
-only_bootstrap = pytest.mark.only('bootstrap', 'bootstrap3', 'bootstrap4')
-only_bootstrap3 = pytest.mark.only('bootstrap3')
-only_bootstrap4 = pytest.mark.only('bootstrap4')
+only_uni_form = pytest.mark.only("uni_form")
+only_bootstrap = pytest.mark.only("bootstrap", "bootstrap3", "bootstrap4")
+only_bootstrap3 = pytest.mark.only("bootstrap3")
+only_bootstrap4 = pytest.mark.only("bootstrap4")
@pytest.fixture
def advanced_layout():
return Layout(
Div(
- Div(Div('email')),
- Div(Field('password1')),
+ Div(Div("email")),
+ Div(Field("password1")),
Submit("save", "save"),
- Fieldset(
- "legend",
- 'first_name',
- HTML("extra text"),
- ),
- Layout(
- "password2",
- ),
+ Fieldset("legend", "first_name", HTML("extra text"),),
+ Layout("password2",),
),
- 'last_name',
+ "last_name",
)
-@pytest.fixture(autouse=True, params=('uni_form', 'bootstrap', 'bootstrap3',
- 'bootstrap4'))
+@pytest.fixture(autouse=True, params=("uni_form", "bootstrap", "bootstrap3", "bootstrap4"))
def template_packs(request, settings):
check_template_pack(request.node, request.param)
settings.CRISPY_TEMPLATE_PACK = request.param
def check_template_pack(node, template_pack):
- mark = node.get_closest_marker('only')
+ mark = node.get_closest_marker("only")
if mark:
if template_pack not in mark.args:
- pytest.skip('Requires %s template pack' % ' or '.join(mark.args))
+ pytest.skip("Requires %s template pack" % " or ".join(mark.args))
diff --git a/crispy_forms/tests/forms.py b/crispy_forms/tests/forms.py
index 4a2ac1779..a1410416f 100644
--- a/crispy_forms/tests/forms.py
+++ b/crispy_forms/tests/forms.py
@@ -6,7 +6,9 @@
class SampleForm(forms.Form):
is_company = forms.CharField(label="company", required=False, widget=forms.CheckboxInput())
- email = forms.EmailField(label="email", max_length=30, required=True, widget=forms.TextInput(), help_text="Insert your email")
+ email = forms.EmailField(
+ label="email", max_length=30, required=True, widget=forms.TextInput(), help_text="Insert your email"
+ )
password1 = forms.CharField(label="password", max_length=30, required=True, widget=forms.PasswordInput())
password2 = forms.CharField(label="re-enter password", max_length=30, required=True, widget=forms.PasswordInput())
first_name = forms.CharField(label="first name", max_length=5, required=True, widget=forms.TextInput())
@@ -15,8 +17,8 @@ class SampleForm(forms.Form):
def clean(self):
super().clean()
- password1 = self.cleaned_data.get('password1', None)
- password2 = self.cleaned_data.get('password2', None)
+ password1 = self.cleaned_data.get("password1", None)
+ password2 = self.cleaned_data.get("password2", None)
if not password1 and not password2 or password1 != password2:
raise forms.ValidationError("Passwords dont match")
@@ -31,42 +33,27 @@ def __init__(self, *args, **kwargs):
class CheckboxesSampleForm(forms.Form):
checkboxes = forms.MultipleChoiceField(
- choices=(
- (1, "Option one"),
- (2, "Option two"),
- (3, "Option three")
- ),
+ choices=((1, "Option one"), (2, "Option two"), (3, "Option three")),
initial=(1,),
widget=forms.CheckboxSelectMultiple,
)
alphacheckboxes = forms.MultipleChoiceField(
- choices=(
- ('option_one', "Option one"),
- ('option_two', "Option two"),
- ('option_three', "Option three")
- ),
- initial=('option_two', 'option_three'),
+ choices=(("option_one", "Option one"), ("option_two", "Option two"), ("option_three", "Option three")),
+ initial=("option_two", "option_three"),
widget=forms.CheckboxSelectMultiple,
)
numeric_multiple_checkboxes = forms.MultipleChoiceField(
- choices=(
- (1, "Option one"),
- (2, "Option two"),
- (3, "Option three")
- ),
+ choices=((1, "Option one"), (2, "Option two"), (3, "Option three")),
initial=(1, 2),
widget=forms.CheckboxSelectMultiple,
)
inline_radios = forms.ChoiceField(
- choices=(
- ('option_one', "Option one"),
- ('option_two', "Option two"),
- ),
+ choices=(("option_one", "Option one"), ("option_two", "Option two"),),
widget=forms.RadioSelect,
- initial='option_two',
+ initial="option_two",
)
@@ -78,8 +65,8 @@ class CrispyTestModel(models.Model):
class SampleForm3(forms.ModelForm):
class Meta:
model = CrispyTestModel
- fields = ['email', 'password']
- exclude = ['password']
+ fields = ["email", "password"]
+ exclude = ["password"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -94,8 +81,9 @@ class Meta:
django.core.exceptions.FieldError: Unknown field(s) (a, l, _) specified for CrispyTestModel
because obviously it casts the string to a set
"""
+
model = CrispyTestModel
- fields = '__all__' # eliminate RemovedInDjango18Warning
+ fields = "__all__" # eliminate RemovedInDjango18Warning
class SampleForm5(forms.Form):
@@ -104,21 +92,15 @@ class SampleForm5(forms.Form):
(2, 2),
(1000, 1000),
]
- checkbox_select_multiple = forms.MultipleChoiceField(
- widget=forms.CheckboxSelectMultiple,
- choices=choices
- )
- radio_select = forms.ChoiceField(
- widget=forms.RadioSelect,
- choices=choices
- )
+ checkbox_select_multiple = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=choices)
+ radio_select = forms.ChoiceField(widget=forms.RadioSelect, choices=choices)
pk = forms.IntegerField()
class SampleFormWithMedia(forms.Form):
class Media:
- css = {'all': ('test.css',)}
- js = ('test.js',)
+ css = {"all": ("test.css",)}
+ js = ("test.js",)
class SampleFormWithMultiValueField(forms.Form):
@@ -126,13 +108,7 @@ class SampleFormWithMultiValueField(forms.Form):
class CrispyEmptyChoiceTestModel(models.Model):
- fruit = models.CharField(
- choices=[
- ('apple', 'Apple'),
- ('pear', 'Pear')],
- null=True,
- blank=True,
- )
+ fruit = models.CharField(choices=[("apple", "Apple"), ("pear", "Pear")], null=True, blank=True,)
class SampleForm6(forms.ModelForm):
@@ -146,9 +122,10 @@ class Meta:
with initial value None, this choice should
be selected.
"""
+
model = CrispyEmptyChoiceTestModel
- fields = ['fruit']
- widgets = {'fruit': forms.RadioSelect()}
+ fields = ["fruit"]
+ widgets = {"fruit": forms.RadioSelect()}
class SampleForm7(forms.ModelForm):
@@ -157,7 +134,7 @@ class SampleForm7(forms.ModelForm):
class Meta:
model = CrispyTestModel
- fields = ('email', 'password', 'password2')
+ fields = ("email", "password", "password2")
class SampleForm8(forms.ModelForm):
@@ -166,4 +143,4 @@ class SampleForm8(forms.ModelForm):
class Meta:
model = CrispyTestModel
- fields = ('email', 'password2', 'password')
+ fields = ("email", "password2", "password")
diff --git a/crispy_forms/tests/test_dynamic_api.py b/crispy_forms/tests/test_dynamic_api.py
index 246d150a3..6c7f31c24 100644
--- a/crispy_forms/tests/test_dynamic_api.py
+++ b/crispy_forms/tests/test_dynamic_api.py
@@ -13,30 +13,22 @@
def test_wrap_all_fields():
helper = FormHelper()
- layout = Layout(
- 'email',
- 'password1',
- 'password2',
- )
+ layout = Layout("email", "password1", "password2",)
helper.layout = layout
helper.all().wrap(Field, css_class="test-class")
for field in layout.fields:
assert isinstance(field, Field)
- assert field.attrs['class'] == "test-class"
+ assert field.attrs["class"] == "test-class"
- assert layout[0][0] == 'email'
- assert layout[1][0] == 'password1'
- assert layout[2][0] == 'password2'
+ assert layout[0][0] == "email"
+ assert layout[1][0] == "password1"
+ assert layout[2][0] == "password2"
def test_wrap_selected_fields():
helper = FormHelper()
- layout = Layout(
- 'email',
- 'password1',
- 'password2',
- )
+ layout = Layout("email", "password1", "password2",)
helper.layout = layout
helper[1:3].wrap(Field, css_class="test-class")
@@ -44,131 +36,91 @@ def test_wrap_selected_fields():
assert isinstance(layout.fields[1], Field)
assert isinstance(layout.fields[2], Field)
- helper[0].wrap(Fieldset, 'legend', css_class="test-class")
+ helper[0].wrap(Fieldset, "legend", css_class="test-class")
assert isinstance(layout[0], Fieldset)
- assert layout[0].legend == 'legend'
- assert layout[0][0] == 'email'
+ assert layout[0].legend == "legend"
+ assert layout[0][0] == "email"
def test_wrap_together_with_slices():
helper = FormHelper()
- layout = Layout(
- 'email',
- 'password1',
- 'password2',
- )
+ layout = Layout("email", "password1", "password2",)
helper.layout = layout
helper[1:3].wrap_together(Field, css_class="test-class")
- assert layout.fields[0] == 'email'
+ assert layout.fields[0] == "email"
assert isinstance(layout.fields[1], Field)
- assert layout.fields[1][0] == 'password1'
- assert layout.fields[1][1] == 'password2'
-
- layout = Layout(
- Div('email'),
- 'password1',
- 'password2',
- )
+ assert layout.fields[1][0] == "password1"
+ assert layout.fields[1][1] == "password2"
+
+ layout = Layout(Div("email"), "password1", "password2",)
helper.layout = layout
helper[0:3].wrap_together(Field, css_class="test-class")
assert isinstance(layout.fields[0], Field)
assert isinstance(layout.fields[0][0], Div)
- assert layout.fields[0][0][0] == 'email'
- assert layout.fields[0][1] == 'password1'
- assert layout.fields[0][2] == 'password2'
-
- layout = Layout(
- 'email',
- 'password1',
- 'password2',
- )
+ assert layout.fields[0][0][0] == "email"
+ assert layout.fields[0][1] == "password1"
+ assert layout.fields[0][2] == "password2"
+
+ layout = Layout("email", "password1", "password2",)
helper.layout = layout
helper[0].wrap_together(Field, css_class="test-class")
assert isinstance(layout.fields[0], Field)
- assert layout.fields[1] == 'password1'
- assert layout.fields[2] == 'password2'
-
- layout = Layout(
- 'email',
- 'password1',
- 'password2',
- )
+ assert layout.fields[1] == "password1"
+ assert layout.fields[2] == "password2"
+
+ layout = Layout("email", "password1", "password2",)
helper.layout = layout
helper[0].wrap_together(Fieldset, "legend", css_class="test-class")
assert isinstance(layout.fields[0], Fieldset)
- assert layout.fields[0].legend == 'legend'
- assert layout.fields[1] == 'password1'
- assert layout.fields[2] == 'password2'
+ assert layout.fields[0].legend == "legend"
+ assert layout.fields[1] == "password1"
+ assert layout.fields[2] == "password2"
def test_wrap_together_partial_slices():
helper = FormHelper()
- layout = Layout(
- 'email',
- 'password1',
- 'password2',
- )
+ layout = Layout("email", "password1", "password2",)
helper.layout = layout
helper[:2].wrap_together(Field, css_class="test-class")
assert isinstance(layout.fields[0], Field)
- assert layout.fields[1] == 'password2'
- assert layout.fields[0][0] == 'email'
- assert layout.fields[0][1] == 'password1'
+ assert layout.fields[1] == "password2"
+ assert layout.fields[0][0] == "email"
+ assert layout.fields[0][1] == "password1"
helper = FormHelper()
- layout = Layout(
- 'email',
- 'password1',
- 'password2',
- )
+ layout = Layout("email", "password1", "password2",)
helper.layout = layout
helper[1:].wrap_together(Field, css_class="test-class")
- assert layout.fields[0] == 'email'
+ assert layout.fields[0] == "email"
assert isinstance(layout.fields[1], Field)
- assert layout.fields[1][0] == 'password1'
- assert layout.fields[1][1] == 'password2'
+ assert layout.fields[1][0] == "password1"
+ assert layout.fields[1][1] == "password2"
def test_update_attributes():
helper = FormHelper()
- helper.layout = Layout(
- 'email',
- Field('password1'),
- 'password2',
- )
- helper['password1'].update_attributes(readonly=True)
- assert 'readonly' in helper.layout[1].attrs
+ helper.layout = Layout("email", Field("password1"), "password2",)
+ helper["password1"].update_attributes(readonly=True)
+ assert "readonly" in helper.layout[1].attrs
def test_update_attributes_and_wrap_once():
helper = FormHelper()
- layout = Layout(
- 'email',
- Field('password1'),
- 'password2',
- )
+ layout = Layout("email", Field("password1"), "password2",)
helper.layout = layout
helper.filter(Field).update_attributes(readonly=True)
assert isinstance(layout[1], Field)
- assert layout[1].attrs == {'readonly': True}
+ assert layout[1].attrs == {"readonly": True}
- layout = Layout(
- 'email',
- Div(Field('password1')),
- 'password2',
- )
+ layout = Layout("email", Div(Field("password1")), "password2",)
helper.layout = layout
helper.filter(Field, max_level=2).update_attributes(readonly=True)
assert isinstance(layout[1][0], Field)
- assert layout[1][0].attrs == {'readonly': True}
+ assert layout[1][0].attrs == {"readonly": True}
- layout = Layout(
- 'email',
- Div(Field('password1')),
- 'password2',
- )
+ layout = Layout("email", Div(Field("password1")), "password2",)
helper.layout = layout
helper.filter(str, greedy=True).wrap_once(Field)
@@ -178,191 +130,104 @@ def test_update_attributes_and_wrap_once():
assert isinstance(layout[1][0], Field)
assert isinstance(layout[1][0][0], str)
assert isinstance(layout[2], Field)
- assert layout[1][0].attrs == {'readonly': True}
- assert layout[0].attrs == {'readonly': True}
- assert layout[2].attrs == {'readonly': True}
+ assert layout[1][0].attrs == {"readonly": True}
+ assert layout[0].attrs == {"readonly": True}
+ assert layout[2].attrs == {"readonly": True}
def test_get_layout_objects():
- layout_1 = Layout(
- Div()
- )
- assert layout_1.get_layout_objects(Div) == [[[0], 'div']]
-
- layout_2 = Layout(
- Div(
- Div(
- Div('email')
- ),
- Div('password1'),
- 'password2'
- )
- )
- assert layout_2.get_layout_objects(Div) == [[[0], 'div']]
- assert layout_2.get_layout_objects(Div, max_level=1) == [
- [[0], 'div'],
- [[0, 0], 'div'],
- [[0, 1], 'div']
- ]
+ layout_1 = Layout(Div())
+ assert layout_1.get_layout_objects(Div) == [[[0], "div"]]
+
+ layout_2 = Layout(Div(Div(Div("email")), Div("password1"), "password2"))
+ assert layout_2.get_layout_objects(Div) == [[[0], "div"]]
+ assert layout_2.get_layout_objects(Div, max_level=1) == [[[0], "div"], [[0, 0], "div"], [[0, 1], "div"]]
assert layout_2.get_layout_objects(Div, max_level=2) == [
- [[0], 'div'],
- [[0, 0], 'div'],
- [[0, 0, 0], 'div'],
- [[0, 1], 'div']
+ [[0], "div"],
+ [[0, 0], "div"],
+ [[0, 0, 0], "div"],
+ [[0, 1], "div"],
]
- layout_3 = Layout(
- 'email',
- Div('password1'),
- 'password2',
- )
- assert layout_3.get_layout_objects(str, max_level=2) == [
- [[0], 'email'],
- [[1, 0], 'password1'],
- [[2], 'password2']
- ]
+ layout_3 = Layout("email", Div("password1"), "password2",)
+ assert layout_3.get_layout_objects(str, max_level=2) == [[[0], "email"], [[1, 0], "password1"], [[2], "password2"]]
- layout_4 = Layout(
- Div(
- Div('field_name'),
- 'field_name2',
- ),
- Div('password'),
- 'extra_field'
- )
- assert layout_4.get_layout_objects(Div) == [
- [[0], 'div'],
- [[1], 'div']
- ]
- assert layout_4.get_layout_objects(Div, max_level=1) == [
- [[0], 'div'],
- [[0, 0], 'div'],
- [[1], 'div']
- ]
+ layout_4 = Layout(Div(Div("field_name"), "field_name2",), Div("password"), "extra_field")
+ assert layout_4.get_layout_objects(Div) == [[[0], "div"], [[1], "div"]]
+ assert layout_4.get_layout_objects(Div, max_level=1) == [[[0], "div"], [[0, 0], "div"], [[1], "div"]]
def test_filter_and_wrap():
helper = FormHelper()
- layout = Layout(
- 'email',
- Div('password1'),
- 'password2',
- )
+ layout = Layout("email", Div("password1"), "password2",)
helper.layout = layout
helper.filter(str).wrap(Field, css_class="test-class")
assert isinstance(layout.fields[0], Field)
assert isinstance(layout.fields[1], Div)
assert isinstance(layout.fields[2], Field)
- assert layout[2][0] == 'password2'
+ assert layout[2][0] == "password2"
# Wrapping a div in a div
helper.filter(Div).wrap(Div, css_class="test-class")
assert isinstance(layout.fields[1], Div)
assert isinstance(layout.fields[1].fields[0], Div)
- assert layout[1][0][0] == 'password1'
+ assert layout[1][0][0] == "password1"
def test_filter_and_wrap_side_effects():
helper = FormHelper()
- layout = Layout(
- Div(
- 'extra_field',
- Div('password1'),
- ),
- )
+ layout = Layout(Div("extra_field", Div("password1"),),)
helper.layout = layout
with pytest.raises(DynamicError):
helper.filter(Div, max_level=2).wrap(Div, css_class="test-class")
def test_get_field_names():
- layout_1 = Div(
- 'field_name'
- )
- assert layout_1.get_field_names() == [
- [[0], 'field_name']
- ]
+ layout_1 = Div("field_name")
+ assert layout_1.get_field_names() == [[[0], "field_name"]]
- layout_2 = Div(
- Div('field_name')
- )
- assert layout_2.get_field_names() == [
- [[0, 0], 'field_name']
- ]
+ layout_2 = Div(Div("field_name"))
+ assert layout_2.get_field_names() == [[[0, 0], "field_name"]]
- layout_3 = Div(
- Div('field_name'),
- 'password'
- )
- assert layout_3.get_field_names() == [
- [[0, 0], 'field_name'],
- [[1], 'password']
- ]
+ layout_3 = Div(Div("field_name"), "password")
+ assert layout_3.get_field_names() == [[[0, 0], "field_name"], [[1], "password"]]
- layout_4 = Div(
- Div(
- Div('field_name'),
- 'field_name2',
- ),
- Div('password'),
- 'extra_field'
- )
+ layout_4 = Div(Div(Div("field_name"), "field_name2",), Div("password"), "extra_field")
assert layout_4.get_field_names() == [
- [[0, 0, 0], 'field_name'],
- [[0, 1], 'field_name2'],
- [[1, 0], 'password'],
- [[2], 'extra_field']
+ [[0, 0, 0], "field_name"],
+ [[0, 1], "field_name2"],
+ [[1, 0], "password"],
+ [[2], "extra_field"],
]
- layout_5 = Div(
- Div(
- 'field_name',
- 'field_name2',
- ),
- 'extra_field'
- )
+ layout_5 = Div(Div("field_name", "field_name2",), "extra_field")
assert layout_5.get_field_names() == [
- [[0, 0], 'field_name'],
- [[0, 1], 'field_name2'],
- [[1], 'extra_field'],
+ [[0, 0], "field_name"],
+ [[0, 1], "field_name2"],
+ [[1], "extra_field"],
]
def test_layout_get_field_names():
- layout_1 = Layout(
- Div('field_name'),
- 'password'
- )
+ layout_1 = Layout(Div("field_name"), "password")
assert layout_1.get_field_names() == [
- [[0, 0], 'field_name'],
- [[1], 'password'],
+ [[0, 0], "field_name"],
+ [[1], "password"],
]
- layout_2 = Layout(
- Div('field_name'),
- 'password',
- Fieldset('legend', 'extra_field')
- )
+ layout_2 = Layout(Div("field_name"), "password", Fieldset("legend", "extra_field"))
assert layout_2.get_field_names() == [
- [[0, 0], 'field_name'],
- [[1], 'password'],
- [[2, 0], 'extra_field'],
+ [[0, 0], "field_name"],
+ [[1], "password"],
+ [[2, 0], "extra_field"],
]
- layout_3 = Layout(
- Div(
- Div(
- Div('email')
- ),
- Div('password1'),
- 'password2'
- )
- )
+ layout_3 = Layout(Div(Div(Div("email")), Div("password1"), "password2"))
assert layout_3.get_field_names() == [
- [[0, 0, 0, 0], 'email'],
- [[0, 1, 0], 'password1'],
- [[0, 2], 'password2'],
+ [[0, 0, 0, 0], "email"],
+ [[0, 1, 0], "password1"],
+ [[0, 2], "password2"],
]
@@ -371,8 +236,8 @@ def test_filter_by_widget(advanced_layout):
form.helper = FormHelper(form)
form.helper.layout = advanced_layout
assert form.helper.filter_by_widget(forms.PasswordInput).slice == [
- [[0, 1, 0, 0], 'password1'],
- [[0, 4, 0], 'password2'],
+ [[0, 1, 0, 0], "password1"],
+ [[0, 4, 0], "password2"],
]
@@ -381,9 +246,9 @@ def test_exclude_by_widget(advanced_layout):
form.helper = FormHelper(form)
form.helper.layout = advanced_layout
assert form.helper.exclude_by_widget(forms.PasswordInput).slice == [
- [[0, 0, 0, 0], 'email'],
- [[0, 3, 0], 'first_name'],
- [[1], 'last_name'],
+ [[0, 0, 0, 0], "email"],
+ [[0, 3, 0], "first_name"],
+ [[1], "last_name"],
]
@@ -391,7 +256,7 @@ def test_exclude_by_widget_and_wrap(advanced_layout):
form = SampleForm()
form.helper = FormHelper(form)
form.helper.layout = advanced_layout
- form.helper.exclude_by_widget(forms.PasswordInput).wrap(Field, css_class='hero')
+ form.helper.exclude_by_widget(forms.PasswordInput).wrap(Field, css_class="hero")
# Check wrapped fields
assert isinstance(form.helper.layout[0][0][0][0], Field)
assert isinstance(form.helper.layout[0][3][0], Field)
@@ -419,64 +284,44 @@ def test_filter_by_widget_without_form(advanced_layout):
def test_formhelper__getitem__():
helper = FormHelper()
- layout = Layout(
- Div('email'),
- 'password1',
- )
+ layout = Layout(Div("email"), "password1",)
helper.layout = layout
- helper['email'].wrap(Field, css_class='hero')
+ helper["email"].wrap(Field, css_class="hero")
assert isinstance(layout[0][0], Field)
- assert layout[0][0][0] == 'email'
+ assert layout[0][0][0] == "email"
helper = FormHelper()
- helper.layout = Layout('password1')
- helper['password1'].wrap(AppendedText, "extra")
+ helper.layout = Layout("password1")
+ helper["password1"].wrap(AppendedText, "extra")
assert isinstance(helper.layout[0], AppendedText)
- assert helper.layout[0][0] == 'password1'
- assert helper.layout[0].text == 'extra'
+ assert helper.layout[0][0] == "password1"
+ assert helper.layout[0].text == "extra"
def test_formhelper__setitem__():
helper = FormHelper()
- layout = Layout(
- 'first_field',
- Div('email')
- )
+ layout = Layout("first_field", Div("email"))
helper.layout = layout
- helper[0] = 'replaced'
- assert layout[0] == 'replaced'
+ helper[0] = "replaced"
+ assert layout[0] == "replaced"
def test_formhelper__delitem__and__len__():
helper = FormHelper()
- layout = Layout(
- 'first_field',
- Div('email')
- )
+ layout = Layout("first_field", Div("email"))
helper.layout = layout
del helper[0]
assert len(helper) == 1
def test__delitem__and__len__layout_object():
- layout = Layout(
- 'first_field',
- Div('email')
- )
+ layout = Layout("first_field", Div("email"))
del layout[0]
assert len(layout) == 1
def test__getitem__layout_object():
- layout = Layout(
- Div(
- Div(
- Div('email')
- ),
- Div('password1'),
- 'password2'
- )
- )
+ layout = Layout(Div(Div(Div("email")), Div("password1"), "password2"))
assert isinstance(layout[0], Div)
assert isinstance(layout[0][0], Div)
assert isinstance(layout[0][0][0], Div)
@@ -486,44 +331,24 @@ def test__getitem__layout_object():
def test__getattr__append_layout_object():
- layout = Layout(
- Div('email')
- )
- layout.append('password1')
+ layout = Layout(Div("email"))
+ layout.append("password1")
assert isinstance(layout[0], Div)
assert isinstance(layout[0][0], str)
assert isinstance(layout[1], str)
def test__setitem__layout_object():
- layout = Layout(
- Div('email')
- )
- layout[0][0] = 'password1'
+ layout = Layout(Div("email"))
+ layout[0][0] = "password1"
assert isinstance(layout[0], Div)
- assert layout[0][0] == 'password1'
+ assert layout[0][0] == "password1"
@only_uni_form
def test_filter():
helper = FormHelper()
- helper.layout = Layout(
- Div(
- MultiField('field_name'),
- 'field_name2',
- ),
- Div('password'),
- 'extra_field'
- )
- assert helper.filter(Div, MultiField).slice == [
- [[0], 'div'],
- [[1], 'div']
- ]
- assert helper.filter(Div, MultiField, max_level=1).slice == [
- [[0], 'div'],
- [[0, 0], 'multifield'],
- [[1], 'div']
- ]
- assert helper.filter(MultiField, max_level=1).slice == [
- [[0, 0], 'multifield']
- ]
+ helper.layout = Layout(Div(MultiField("field_name"), "field_name2",), Div("password"), "extra_field")
+ assert helper.filter(Div, MultiField).slice == [[[0], "div"], [[1], "div"]]
+ assert helper.filter(Div, MultiField, max_level=1).slice == [[[0], "div"], [[0, 0], "multifield"], [[1], "div"]]
+ assert helper.filter(MultiField, max_level=1).slice == [[[0, 0], "multifield"]]
diff --git a/crispy_forms/tests/test_form_helper.py b/crispy_forms/tests/test_form_helper.py
index f0e27d95f..3979277f5 100644
--- a/crispy_forms/tests/test_form_helper.py
+++ b/crispy_forms/tests/test_form_helper.py
@@ -23,36 +23,38 @@
def test_inputs(settings):
form_helper = FormHelper()
- form_helper.add_input(Submit('my-submit', 'Submit', css_class="button white"))
- form_helper.add_input(Reset('my-reset', 'Reset'))
- form_helper.add_input(Hidden('my-hidden', 'Hidden'))
- form_helper.add_input(Button('my-button', 'Button'))
+ form_helper.add_input(Submit("my-submit", "Submit", css_class="button white"))
+ form_helper.add_input(Reset("my-reset", "Reset"))
+ form_helper.add_input(Hidden("my-hidden", "Hidden"))
+ form_helper.add_input(Button("my-button", "Button"))
- template = Template("""
+ template = Template(
+ """
{% load crispy_forms_tags %}
{% crispy form form_helper %}
- """)
- c = Context({'form': SampleForm(), 'form_helper': form_helper})
+ """
+ )
+ c = Context({"form": SampleForm(), "form_helper": form_helper})
html = template.render(c)
- assert 'button white' in html
+ assert "button white" in html
assert 'id="submit-id-my-submit"' in html
assert 'id="reset-id-my-reset"' in html
assert 'name="my-hidden"' in html
assert 'id="button-id-my-button"' in html
- if settings.CRISPY_TEMPLATE_PACK == 'uni_form':
- assert 'submit submitButton' in html
- assert 'reset resetButton' in html
+ if settings.CRISPY_TEMPLATE_PACK == "uni_form":
+ assert "submit submitButton" in html
+ assert "reset resetButton" in html
assert 'class="button"' in html
else:
assert 'class="btn"' in html
- assert 'btn btn-primary' in html
- assert 'btn btn-inverse' in html
- if settings.CRISPY_TEMPLATE_PACK == 'bootstrap4':
- assert len(re.findall(r'
]+> <', html)) == 9
+ assert "btn btn-primary" in html
+ assert "btn btn-inverse" in html
+ if settings.CRISPY_TEMPLATE_PACK == "bootstrap4":
+ assert len(re.findall(r"
]+> <", html)) == 9
else:
- assert len(re.findall(r'
]+> <', html)) == 8
+ assert len(re.findall(r"
]+> <", html)) == 8
def test_invalid_form_method():
@@ -63,31 +65,33 @@ def test_invalid_form_method():
def test_form_with_helper_without_layout(settings):
form_helper = FormHelper()
- form_helper.form_id = 'this-form-rocks'
- form_helper.form_class = 'forms-that-rock'
- form_helper.form_method = 'GET'
- form_helper.form_action = 'simpleAction'
- form_helper.form_error_title = 'ERRORS'
-
- template = Template("""
+ form_helper.form_id = "this-form-rocks"
+ form_helper.form_class = "forms-that-rock"
+ form_helper.form_method = "GET"
+ form_helper.form_action = "simpleAction"
+ form_helper.form_error_title = "ERRORS"
+
+ template = Template(
+ """
{% load crispy_forms_tags %}
{% crispy testForm form_helper %}
- """)
+ """
+ )
# now we render it, with errors
- form = SampleForm({'password1': 'wargame', 'password2': 'god'})
+ form = SampleForm({"password1": "wargame", "password2": "god"})
form.is_valid()
- c = Context({'testForm': form, 'form_helper': form_helper})
+ c = Context({"testForm": form, "form_helper": form_helper})
html = template.render(c)
# Lets make sure everything loads right
- assert html.count('
')
assert contains_partial(html, '
')
@@ -503,19 +520,17 @@ def test_render_hidden_fields():
def test_render_required_fields():
test_form = SampleForm()
test_form.helper = FormHelper()
- test_form.helper.layout = Layout(
- 'email'
- )
+ test_form.helper.layout = Layout("email")
test_form.helper.render_required_fields = True
html = render_crispy_form(test_form)
- assert html.count('
Special custom form" in html
@@ -524,11 +539,8 @@ def test_helper_custom_template():
def test_helper_custom_field_template():
form = SampleForm()
form.helper = FormHelper()
- form.helper.layout = Layout(
- 'password1',
- 'password2',
- )
- form.helper.field_template = 'custom_field_template.html'
+ form.helper.layout = Layout("password1", "password2",)
+ form.helper.field_template = "custom_field_template.html"
html = render_crispy_form(form)
assert html.count("
Special custom field
") == 2
@@ -537,7 +549,7 @@ def test_helper_custom_field_template():
def test_helper_custom_field_template_no_layout():
form = SampleForm()
form.helper = FormHelper()
- form.helper.field_template = 'custom_field_template.html'
+ form.helper.field_template = "custom_field_template.html"
html = render_crispy_form(form)
for field in form.fields:
@@ -556,167 +568,153 @@ def test_helper_std_field_template_no_layout():
@only_uni_form
def test_form_show_errors():
- form = SampleForm({
- 'email': 'invalidemail',
- 'first_name': 'first_name_too_long',
- 'last_name': 'last_name_too_long',
- 'password1': 'yes',
- 'password2': 'yes',
- })
+ form = SampleForm(
+ {
+ "email": "invalidemail",
+ "first_name": "first_name_too_long",
+ "last_name": "last_name_too_long",
+ "password1": "yes",
+ "password2": "yes",
+ }
+ )
form.helper = FormHelper()
form.helper.layout = Layout(
- Field('email'),
- Field('first_name'),
- Field('last_name'),
- Field('password1'),
- Field('password2'),
+ Field("email"), Field("first_name"), Field("last_name"), Field("password1"), Field("password2"),
)
form.is_valid()
form.helper.form_show_errors = True
html = render_crispy_form(form)
- assert html.count('error') == 9
+ assert html.count("error") == 9
form.helper.form_show_errors = False
html = render_crispy_form(form)
- assert html.count('error') == 0
+ assert html.count("error") == 0
@only_uni_form
def test_multifield_errors():
- form = SampleForm({
- 'email': 'invalidemail',
- 'password1': 'yes',
- 'password2': 'yes',
- })
+ form = SampleForm({"email": "invalidemail", "password1": "yes", "password2": "yes",})
form.helper = FormHelper()
- form.helper.layout = Layout(
- MultiField('legend', 'email')
- )
+ form.helper.layout = Layout(MultiField("legend", "email"))
form.is_valid()
form.helper.form_show_errors = True
html = render_crispy_form(form)
- assert html.count('error') == 3
+ assert html.count("error") == 3
# Reset layout for avoiding side effects
- form.helper.layout = Layout(
- MultiField('legend', 'email')
- )
+ form.helper.layout = Layout(MultiField("legend", "email"))
form.helper.form_show_errors = False
html = render_crispy_form(form)
- assert html.count('error') == 0
+ assert html.count("error") == 0
@only_bootstrap3
def test_bootstrap_form_show_errors_bs3():
- form = SampleForm({
- 'email': 'invalidemail',
- 'first_name': 'first_name_too_long',
- 'last_name': 'last_name_too_long',
- 'password1': 'yes',
- 'password2': 'yes',
- })
+ form = SampleForm(
+ {
+ "email": "invalidemail",
+ "first_name": "first_name_too_long",
+ "last_name": "last_name_too_long",
+ "password1": "yes",
+ "password2": "yes",
+ }
+ )
form.helper = FormHelper()
form.helper.layout = Layout(
- AppendedText('email', 'whatever'),
- PrependedText('first_name', 'blabla'),
- PrependedAppendedText('last_name', 'foo', 'bar'),
- AppendedText('password1', 'whatever'),
- PrependedText('password2', 'blabla'),
+ AppendedText("email", "whatever"),
+ PrependedText("first_name", "blabla"),
+ PrependedAppendedText("last_name", "foo", "bar"),
+ AppendedText("password1", "whatever"),
+ PrependedText("password2", "blabla"),
)
form.is_valid()
form.helper.form_show_errors = True
html = render_crispy_form(form)
- assert html.count('error') == 6
+ assert html.count("error") == 6
form.helper.form_show_errors = False
html = render_crispy_form(form)
- assert html.count('error') == 0
+ assert html.count("error") == 0
@only_bootstrap4
def test_bootstrap_form_show_errors_bs4():
- form = SampleForm({
- 'email': 'invalidemail',
- 'first_name': 'first_name_too_long',
- 'last_name': 'last_name_too_long',
- 'password1': 'yes',
- 'password2': 'yes',
- })
+ form = SampleForm(
+ {
+ "email": "invalidemail",
+ "first_name": "first_name_too_long",
+ "last_name": "last_name_too_long",
+ "password1": "yes",
+ "password2": "yes",
+ }
+ )
form.helper = FormHelper()
form.helper.layout = Layout(
- AppendedText('email', 'whatever'),
- PrependedText('first_name', 'blabla'),
- PrependedAppendedText('last_name', 'foo', 'bar'),
- AppendedText('password1', 'whatever'),
- PrependedText('password2', 'blabla'),
+ AppendedText("email", "whatever"),
+ PrependedText("first_name", "blabla"),
+ PrependedAppendedText("last_name", "foo", "bar"),
+ AppendedText("password1", "whatever"),
+ PrependedText("password2", "blabla"),
)
form.is_valid()
form.helper.form_show_errors = True
html = render_crispy_form(form)
- assert html.count('error') == 3
+ assert html.count("error") == 3
form.helper.form_show_errors = False
html = render_crispy_form(form)
- assert html.count('error') == 0
+ assert html.count("error") == 0
@only_bootstrap
def test_error_text_inline(settings):
- form = SampleForm({'email': 'invalidemail'})
+ form = SampleForm({"email": "invalidemail"})
form.helper = FormHelper()
layout = Layout(
- AppendedText('first_name', 'wat'),
- PrependedText('email', '@'),
- PrependedAppendedText('last_name', '@', 'wat'),
+ AppendedText("first_name", "wat"), PrependedText("email", "@"), PrependedAppendedText("last_name", "@", "wat"),
)
form.helper.layout = layout
form.is_valid()
html = render_crispy_form(form)
- help_class = 'help-inline'
- help_tag_name = 'p'
- if settings.CRISPY_TEMPLATE_PACK == 'bootstrap3':
- help_class = 'help-block'
- elif settings.CRISPY_TEMPLATE_PACK == 'bootstrap4':
- help_class = 'invalid-feedback'
- help_tag_name = 'div'
+ help_class = "help-inline"
+ help_tag_name = "p"
+ if settings.CRISPY_TEMPLATE_PACK == "bootstrap3":
+ help_class = "help-block"
+ elif settings.CRISPY_TEMPLATE_PACK == "bootstrap4":
+ help_class = "invalid-feedback"
+ help_tag_name = "div"
- matches = re.findall(
- r'