login page
This commit is contained in:
1
Lib/site-packages/crispy_forms/__init__.py
Normal file
1
Lib/site-packages/crispy_forms/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__version__ = "1.9.2"
|
||||
Binary file not shown.
BIN
Lib/site-packages/crispy_forms/__pycache__/base.cpython-38.pyc
Normal file
BIN
Lib/site-packages/crispy_forms/__pycache__/base.cpython-38.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Lib/site-packages/crispy_forms/__pycache__/helper.cpython-38.pyc
Normal file
BIN
Lib/site-packages/crispy_forms/__pycache__/helper.cpython-38.pyc
Normal file
Binary file not shown.
BIN
Lib/site-packages/crispy_forms/__pycache__/layout.cpython-38.pyc
Normal file
BIN
Lib/site-packages/crispy_forms/__pycache__/layout.cpython-38.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
Lib/site-packages/crispy_forms/__pycache__/utils.cpython-38.pyc
Normal file
BIN
Lib/site-packages/crispy_forms/__pycache__/utils.cpython-38.pyc
Normal file
Binary file not shown.
22
Lib/site-packages/crispy_forms/base.py
Normal file
22
Lib/site-packages/crispy_forms/base.py
Normal file
@@ -0,0 +1,22 @@
|
||||
class KeepContext:
|
||||
"""
|
||||
Context manager that receives a `django.template.Context` instance and a list of keys
|
||||
|
||||
Once the context manager is exited, it removes `keys` from the context, to avoid
|
||||
side effects in later layout objects that may use the same context variables.
|
||||
|
||||
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
|
||||
|
||||
def __enter__(self):
|
||||
pass
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
for key in list(self.keys):
|
||||
if key in self.context:
|
||||
del self.context[key]
|
||||
409
Lib/site-packages/crispy_forms/bootstrap.py
Normal file
409
Lib/site-packages/crispy_forms/bootstrap.py
Normal file
@@ -0,0 +1,409 @@
|
||||
from random import randint
|
||||
|
||||
from django.template import Template
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from .layout import Div, Field, LayoutObject, TemplateNameMixin
|
||||
from .utils import TEMPLATE_PACK, flatatt, render_field
|
||||
|
||||
|
||||
class PrependedAppendedText(Field):
|
||||
template = "%s/layout/prepended_appended_text.html"
|
||||
|
||||
def __init__(self, field, prepended_text=None, appended_text=None, *args, **kwargs):
|
||||
self.field = field
|
||||
self.appended_text = appended_text
|
||||
self.prepended_text = prepended_text
|
||||
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"
|
||||
|
||||
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
|
||||
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,
|
||||
)
|
||||
|
||||
|
||||
class AppendedText(PrependedAppendedText):
|
||||
def __init__(self, field, text, *args, **kwargs):
|
||||
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)
|
||||
self.text = text
|
||||
super().__init__(field, prepended_text=text, **kwargs)
|
||||
|
||||
|
||||
class FormActions(LayoutObject):
|
||||
"""
|
||||
Bootstrap layout object. It wraps fields in a <div class="form-actions">
|
||||
|
||||
Example::
|
||||
|
||||
FormActions(
|
||||
HTML(<span style="display: hidden;">Information Saved</span>),
|
||||
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.attrs = kwargs
|
||||
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})
|
||||
|
||||
return render_to_string(template, context.flatten())
|
||||
|
||||
def flat_attrs(self):
|
||||
return flatatt(self.attrs)
|
||||
|
||||
|
||||
class InlineCheckboxes(Field):
|
||||
"""
|
||||
Layout object for rendering checkboxes inline::
|
||||
|
||||
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"}
|
||||
)
|
||||
|
||||
|
||||
class InlineRadios(Field):
|
||||
"""
|
||||
Layout object for rendering radiobuttons inline::
|
||||
|
||||
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"}
|
||||
)
|
||||
|
||||
|
||||
class FieldWithButtons(Div):
|
||||
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(
|
||||
render_field(
|
||||
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}
|
||||
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,
|
||||
)
|
||||
else:
|
||||
return render_field(
|
||||
self.fields[0], form, form_style, context, template, extra_context=extra_context, **kwargs
|
||||
)
|
||||
|
||||
|
||||
class StrictButton(TemplateNameMixin):
|
||||
"""
|
||||
Layout object for rendering an HTML button::
|
||||
|
||||
Button("button content", css_class="extra")
|
||||
"""
|
||||
|
||||
template = "%s/layout/button.html"
|
||||
field_classes = "btn"
|
||||
|
||||
def __init__(self, content, **kwargs):
|
||||
self.content = content
|
||||
self.template = kwargs.pop("template", self.template)
|
||||
|
||||
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")
|
||||
|
||||
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})
|
||||
|
||||
return render_to_string(template, context.flatten())
|
||||
|
||||
|
||||
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.name = name
|
||||
self._active_originally_included = "active" in kwargs
|
||||
self.active = kwargs.pop("active", False)
|
||||
if not self.css_id:
|
||||
self.css_id = slugify(self.name)
|
||||
|
||||
def __contains__(self, field_name):
|
||||
"""
|
||||
check if field_name is contained within tab.
|
||||
"""
|
||||
return field_name in map(lambda pointer: pointer[1], self.get_field_names())
|
||||
|
||||
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"
|
||||
else:
|
||||
self.css_class = self.css_class.replace("active", "")
|
||||
return super().render(form, form_style, context, template_pack)
|
||||
|
||||
|
||||
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.
|
||||
"""
|
||||
for tab in self.fields:
|
||||
errors_here = any(error in tab for error in errors)
|
||||
if errors_here:
|
||||
return tab
|
||||
return None
|
||||
|
||||
def open_target_group_for_form(self, form):
|
||||
"""
|
||||
Makes sure that the first group that should be open is open.
|
||||
This is either the first group with errors or the first group
|
||||
in the container, unless that first group was originally set to
|
||||
active=False.
|
||||
"""
|
||||
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):
|
||||
target.active = True
|
||||
return target
|
||||
|
||||
target.active = True
|
||||
return target
|
||||
|
||||
|
||||
class Tab(Container):
|
||||
"""
|
||||
Tab object. It wraps fields in a div whose default class is "tab-pane" and
|
||||
takes a name as first argument. Example::
|
||||
|
||||
Tab('tab_name', 'form_field_1', 'form_field_2', 'form_field_3')
|
||||
"""
|
||||
|
||||
css_class = "tab-pane"
|
||||
link_template = "%s/layout/tab-link.html"
|
||||
|
||||
def render_link(self, template_pack=TEMPLATE_PACK, **kwargs):
|
||||
"""
|
||||
Render the link for the tab-pane. It must be called after render so css_class is updated
|
||||
with active if needed.
|
||||
"""
|
||||
link_template = self.link_template % template_pack
|
||||
return render_to_string(link_template, {"link": self})
|
||||
|
||||
|
||||
class TabHolder(ContainerHolder):
|
||||
"""
|
||||
TabHolder object. It wraps Tab objects in a container. Requires bootstrap-tab.js::
|
||||
|
||||
TabHolder(
|
||||
Tab('form_field_1', 'form_field_2'),
|
||||
Tab('form_field_3')
|
||||
)
|
||||
"""
|
||||
|
||||
template = "%s/layout/tab.html"
|
||||
|
||||
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
|
||||
for tab in self.fields:
|
||||
tab.active = False
|
||||
|
||||
# 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)
|
||||
|
||||
context.update({"tabs": self, "links": links, "content": content})
|
||||
template = self.get_template_name(template_pack)
|
||||
return render_to_string(template, context.flatten())
|
||||
|
||||
|
||||
class AccordionGroup(Container):
|
||||
"""
|
||||
Accordion Group (pane) object. It wraps given fields inside an accordion
|
||||
tab. It takes accordion tab name as first argument::
|
||||
|
||||
AccordionGroup("group name", "form_field_1", "form_field_2")
|
||||
"""
|
||||
|
||||
template = "%s/accordion-group.html"
|
||||
data_parent = "" # accordion parent div id.
|
||||
|
||||
|
||||
class Accordion(ContainerHolder):
|
||||
"""
|
||||
Accordion menu object. It wraps `AccordionGroup` objects in a container::
|
||||
|
||||
Accordion(
|
||||
AccordionGroup("group name", "form_field_1", "form_field_2"),
|
||||
AccordionGroup("another group name", "form_field")
|
||||
)
|
||||
"""
|
||||
|
||||
template = "%s/accordion.html"
|
||||
|
||||
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
|
||||
content = ""
|
||||
|
||||
# accordion group needs the parent div id to set `data-parent` (I don't
|
||||
# know why). This needs to be a unique id
|
||||
if not self.css_id:
|
||||
self.css_id = "-".join(["accordion", str(randint(1000, 9999))])
|
||||
|
||||
# Open the group that should be open.
|
||||
self.open_target_group_for_form(form)
|
||||
|
||||
for group in self.fields:
|
||||
group.data_parent = self.css_id
|
||||
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})
|
||||
|
||||
return render_to_string(template, context.flatten())
|
||||
|
||||
|
||||
class Alert(Div):
|
||||
"""
|
||||
`Alert` generates markup in the form of an alert dialog
|
||||
|
||||
Alert(content='<strong>Warning!</strong> 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"
|
||||
Div.__init__(self, *fields, **kwargs)
|
||||
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})
|
||||
|
||||
return render_to_string(template, context.flatten())
|
||||
|
||||
|
||||
class UneditableField(Field):
|
||||
"""
|
||||
Layout object for rendering fields as uneditable in bootstrap
|
||||
|
||||
Example::
|
||||
|
||||
UneditableField('field_name', css_class="input-xlarge")
|
||||
"""
|
||||
|
||||
template = "%s/layout/uneditable_input.html"
|
||||
|
||||
def __init__(self, field, *args, **kwargs):
|
||||
self.attrs = {"class": "uneditable-input"}
|
||||
super().__init__(field, *args, **kwargs)
|
||||
|
||||
|
||||
class InlineField(Field):
|
||||
template = "%s/layout/inline_field.html"
|
||||
6
Lib/site-packages/crispy_forms/compatibility.py
Normal file
6
Lib/site-packages/crispy_forms/compatibility.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import django
|
||||
|
||||
if django.VERSION < (3, 0):
|
||||
from django.utils.lru_cache import lru_cache # noqa: F401
|
||||
else:
|
||||
from functools import lru_cache # noqa: F401
|
||||
16
Lib/site-packages/crispy_forms/exceptions.py
Normal file
16
Lib/site-packages/crispy_forms/exceptions.py
Normal file
@@ -0,0 +1,16 @@
|
||||
class CrispyError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class FormHelpersException(CrispyError):
|
||||
"""
|
||||
This is raised when building a form via helpers throws an error.
|
||||
We want to catch form helper errors as soon as possible because
|
||||
debugging templatetags is never fun.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class DynamicError(CrispyError):
|
||||
pass
|
||||
388
Lib/site-packages/crispy_forms/helper.py
Normal file
388
Lib/site-packages/crispy_forms/helper.py
Normal file
@@ -0,0 +1,388 @@
|
||||
import re
|
||||
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from crispy_forms.exceptions import FormHelpersException
|
||||
from crispy_forms.layout import Layout
|
||||
from crispy_forms.layout_slice import LayoutSlice
|
||||
from crispy_forms.utils import TEMPLATE_PACK, flatatt, list_difference, render_field
|
||||
|
||||
|
||||
class DynamicLayoutHandler:
|
||||
def _check_layout(self):
|
||||
if self.layout is None:
|
||||
raise FormHelpersException("You need to set a layout in your FormHelper")
|
||||
|
||||
def _check_layout_and_form(self):
|
||||
self._check_layout()
|
||||
if self.form is None:
|
||||
raise FormHelpersException("You need to pass a form instance to your FormHelper")
|
||||
|
||||
def all(self):
|
||||
"""
|
||||
Returns all layout objects of first level of depth
|
||||
"""
|
||||
self._check_layout()
|
||||
return LayoutSlice(self.layout, slice(0, len(self.layout.fields), 1))
|
||||
|
||||
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)
|
||||
filtered_layout_objects = self.layout.get_layout_objects(LayoutClasses, max_level=max_level, greedy=greedy)
|
||||
|
||||
return LayoutSlice(self.layout, filtered_layout_objects)
|
||||
|
||||
def filter_by_widget(self, widget_type):
|
||||
"""
|
||||
Returns a LayoutSlice pointing to fields with widgets of `widget_type`
|
||||
"""
|
||||
self._check_layout_and_form()
|
||||
layout_field_names = self.layout.get_field_names()
|
||||
|
||||
# Let's filter all fields with widgets like widget_type
|
||||
filtered_fields = []
|
||||
for pointer in layout_field_names:
|
||||
if isinstance(self.form.fields[pointer[1]].widget, widget_type):
|
||||
filtered_fields.append(pointer)
|
||||
|
||||
return LayoutSlice(self.layout, filtered_fields)
|
||||
|
||||
def exclude_by_widget(self, widget_type):
|
||||
"""
|
||||
Returns a LayoutSlice pointing to fields with widgets NOT matching `widget_type`
|
||||
"""
|
||||
self._check_layout_and_form()
|
||||
layout_field_names = self.layout.get_field_names()
|
||||
|
||||
# Let's exclude all fields with widgets like widget_type
|
||||
filtered_fields = []
|
||||
for pointer in layout_field_names:
|
||||
if not isinstance(self.form.fields[pointer[1]].widget, widget_type):
|
||||
filtered_fields.append(pointer)
|
||||
|
||||
return LayoutSlice(self.layout, filtered_fields)
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""
|
||||
Return a LayoutSlice that makes changes affect the current instance of the layout
|
||||
and not a copy.
|
||||
"""
|
||||
# when key is a string containing the field name
|
||||
if isinstance(key, str):
|
||||
# Django templates access FormHelper attributes using dictionary [] operator
|
||||
# This could be a helper['form_id'] access, not looking for a field
|
||||
if hasattr(self, key):
|
||||
return getattr(self, key)
|
||||
|
||||
self._check_layout()
|
||||
layout_field_names = self.layout.get_field_names()
|
||||
|
||||
filtered_field = []
|
||||
for pointer in layout_field_names:
|
||||
# There can be an empty pointer
|
||||
if len(pointer) == 2 and pointer[1] == key:
|
||||
filtered_field.append(pointer)
|
||||
|
||||
return LayoutSlice(self.layout, filtered_field)
|
||||
|
||||
return LayoutSlice(self.layout, key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.layout[key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self.layout.fields[key]
|
||||
|
||||
def __len__(self):
|
||||
if self.layout is not None:
|
||||
return len(self.layout.fields)
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
class FormHelper(DynamicLayoutHandler):
|
||||
"""
|
||||
This class controls the form rendering behavior of the form passed to
|
||||
the `{% crispy %}` tag. For doing so you will need to set its attributes
|
||||
and pass the corresponding helper object to the tag::
|
||||
|
||||
{% crispy form form.helper %}
|
||||
|
||||
Let's see what attributes you can set and what form behaviors they apply to:
|
||||
|
||||
**form_method**: Specifies form method attribute.
|
||||
You can set it to 'POST' or 'GET'. Defaults to 'POST'
|
||||
|
||||
**form_action**: Applied to the form action attribute:
|
||||
- Can be a named url in your URLconf that can be executed via the `{% url %}` template tag. \
|
||||
Example: 'show_my_profile'. In your URLconf you could have something like::
|
||||
|
||||
url(r'^show/profile/$', 'show_my_profile_view', name = 'show_my_profile')
|
||||
|
||||
- It can simply point to a URL '/whatever/blabla/'.
|
||||
|
||||
**form_id**: Generates a form id for dom identification.
|
||||
If no id provided then no id attribute is created on the form.
|
||||
|
||||
**form_class**: String containing separated CSS classes to be applied
|
||||
to form class attribute. The form will always have by default
|
||||
'uniForm' class.
|
||||
|
||||
**form_group_wrapper_class**: String containing separated CSS classes to be applied
|
||||
to each row of inputs.
|
||||
|
||||
**form_tag**: It specifies if <form></form> tags should be rendered when using a Layout.
|
||||
If set to False it renders the form without the <form></form> tags. Defaults to True.
|
||||
|
||||
**form_error_title**: If a form has `non_field_errors` to display, they
|
||||
are rendered in a div. You can set title's div with this attribute.
|
||||
Example: "Oooops!" or "Form Errors"
|
||||
|
||||
**formset_error_title**: If a formset has `non_form_errors` to display, they
|
||||
are rendered in a div. You can set title's div with this attribute.
|
||||
|
||||
**form_style**: Uni-form has two built in different form styles. You can choose
|
||||
your favorite. This can be set to "default" or "inline". Defaults to "default".
|
||||
|
||||
**include_media**: Whether to automatically include form media. Set to False if
|
||||
you want to manually include form media outside the form. Defaults to True.
|
||||
|
||||
Public Methods:
|
||||
|
||||
**add_input(input)**: You can add input buttons using this method. Inputs
|
||||
added using this method will be rendered at the end of the form/formset.
|
||||
|
||||
**add_layout(layout)**: You can add a `Layout` object to `FormHelper`. The Layout
|
||||
specifies in a simple, clean and DRY way how the form fields should be rendered.
|
||||
You can wrap fields, order them, customize pretty much anything in the form.
|
||||
|
||||
Best way to add a helper to a form is adding a property named helper to the form
|
||||
that returns customized `FormHelper` object::
|
||||
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Submit
|
||||
|
||||
class MyForm(forms.Form):
|
||||
title = forms.CharField(_("Title"))
|
||||
|
||||
@property
|
||||
def helper(self):
|
||||
helper = FormHelper()
|
||||
helper.form_id = 'this-form-rocks'
|
||||
helper.form_class = 'search'
|
||||
helper.add_input(Submit('save', 'save'))
|
||||
[...]
|
||||
return helper
|
||||
|
||||
You can use it in a template doing::
|
||||
|
||||
{% load crispy_forms_tags %}
|
||||
{% crispy form %}
|
||||
"""
|
||||
|
||||
_form_method = "post"
|
||||
_form_action = ""
|
||||
_form_style = "default"
|
||||
form = None
|
||||
form_id = ""
|
||||
form_class = ""
|
||||
form_group_wrapper_class = ""
|
||||
layout = None
|
||||
form_tag = True
|
||||
form_error_title = None
|
||||
formset_error_title = None
|
||||
form_show_errors = True
|
||||
render_unmentioned_fields = False
|
||||
render_hidden_fields = False
|
||||
render_required_fields = False
|
||||
_help_text_inline = False
|
||||
_error_text_inline = True
|
||||
html5_required = False
|
||||
form_show_labels = True
|
||||
template = None
|
||||
field_template = None
|
||||
disable_csrf = False
|
||||
use_custom_control = True
|
||||
label_class = ""
|
||||
field_class = ""
|
||||
include_media = True
|
||||
|
||||
def __init__(self, form=None):
|
||||
self.attrs = {}
|
||||
self.inputs = []
|
||||
|
||||
if form is not None:
|
||||
self.form = form
|
||||
self.layout = self.build_default_layout(form)
|
||||
|
||||
def build_default_layout(self, form):
|
||||
return Layout(*form.fields.keys())
|
||||
|
||||
@property
|
||||
def form_method(self):
|
||||
return self._form_method
|
||||
|
||||
@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"
|
||||
)
|
||||
|
||||
self._form_method = method.lower()
|
||||
|
||||
@property
|
||||
def form_action(self):
|
||||
try:
|
||||
return reverse(self._form_action)
|
||||
except NoReverseMatch:
|
||||
return self._form_action
|
||||
|
||||
@form_action.setter
|
||||
def form_action(self, action):
|
||||
self._form_action = action
|
||||
|
||||
@property
|
||||
def form_style(self):
|
||||
if self._form_style == "default":
|
||||
return ""
|
||||
|
||||
if self._form_style == "inline":
|
||||
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"
|
||||
)
|
||||
|
||||
self._form_style = style.lower()
|
||||
|
||||
@property
|
||||
def help_text_inline(self):
|
||||
return self._help_text_inline
|
||||
|
||||
@help_text_inline.setter
|
||||
def help_text_inline(self, flag):
|
||||
self._help_text_inline = flag
|
||||
self._error_text_inline = not flag
|
||||
|
||||
@property
|
||||
def error_text_inline(self):
|
||||
return self._error_text_inline
|
||||
|
||||
@error_text_inline.setter
|
||||
def error_text_inline(self, flag):
|
||||
self._error_text_inline = flag
|
||||
self._help_text_inline = not flag
|
||||
|
||||
def add_input(self, input_object):
|
||||
self.inputs.append(input_object)
|
||||
|
||||
def add_layout(self, layout):
|
||||
self.layout = layout
|
||||
|
||||
def render_layout(self, form, context, template_pack=TEMPLATE_PACK):
|
||||
"""
|
||||
Returns safe html of the rendering of the layout
|
||||
"""
|
||||
form.rendered_fields = set()
|
||||
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)
|
||||
|
||||
# Rendering some extra fields if specified
|
||||
if self.render_unmentioned_fields or self.render_hidden_fields or self.render_required_fields:
|
||||
fields = tuple(form.fields.keys())
|
||||
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)
|
||||
):
|
||||
html += render_field(field, form, self.form_style, context, template_pack=template_pack)
|
||||
|
||||
return mark_safe(html)
|
||||
|
||||
def get_attributes(self, template_pack=TEMPLATE_PACK): # noqa: C901
|
||||
"""
|
||||
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,
|
||||
}
|
||||
|
||||
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[0], m[-1]) for m in bootstrap_size_match
|
||||
]
|
||||
else:
|
||||
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]
|
||||
|
||||
items["attrs"] = {}
|
||||
if self.attrs:
|
||||
items["attrs"] = self.attrs.copy()
|
||||
if self.form_action:
|
||||
items["attrs"]["action"] = self.form_action.strip()
|
||||
if self.form_id:
|
||||
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()
|
||||
else:
|
||||
items["attrs"]["class"] = self.form_class.strip()
|
||||
else:
|
||||
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["flat_attrs"] = flatatt(items["attrs"])
|
||||
|
||||
if self.inputs:
|
||||
items["inputs"] = self.inputs
|
||||
if self.form_error_title:
|
||||
items["form_error_title"] = self.form_error_title.strip()
|
||||
if self.formset_error_title:
|
||||
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("_")
|
||||
):
|
||||
items[attribute_name] = value
|
||||
|
||||
return items
|
||||
491
Lib/site-packages/crispy_forms/layout.py
Normal file
491
Lib/site-packages/crispy_forms/layout.py
Normal file
@@ -0,0 +1,491 @@
|
||||
from django.template import Template
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import conditional_escape
|
||||
|
||||
from crispy_forms.utils import TEMPLATE_PACK, flatatt, get_template_pack, render_field
|
||||
|
||||
|
||||
class TemplateNameMixin:
|
||||
def get_template_name(self, template_pack):
|
||||
if "%s" in self.template:
|
||||
template = self.template % template_pack
|
||||
else:
|
||||
template = self.template
|
||||
|
||||
return template
|
||||
|
||||
|
||||
class LayoutObject(TemplateNameMixin):
|
||||
def __getitem__(self, slice):
|
||||
return self.fields[slice]
|
||||
|
||||
def __setitem__(self, slice, value):
|
||||
self.fields[slice] = value
|
||||
|
||||
def __delitem__(self, slice):
|
||||
del self.fields[slice]
|
||||
|
||||
def __len__(self):
|
||||
return len(self.fields)
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""
|
||||
This allows us to access self.fields list methods like append or insert, without
|
||||
having to declare them one by one
|
||||
"""
|
||||
# Check necessary for unpickling, see #107
|
||||
if "fields" in self.__dict__ and hasattr(self.fields, name):
|
||||
return getattr(self.fields, name)
|
||||
else:
|
||||
return object.__getattribute__(self, name)
|
||||
|
||||
def get_field_names(self, index=None):
|
||||
"""
|
||||
Returns a list of lists, those lists are named pointers. First parameter
|
||||
is the location of the field, second one the name of the field. Example::
|
||||
|
||||
[
|
||||
[[0,1,2], 'field_name1'],
|
||||
[[0,3], 'field_name2']
|
||||
]
|
||||
"""
|
||||
return self.get_layout_objects(str, index=None, greedy=True)
|
||||
|
||||
def get_layout_objects(self, *LayoutClasses, **kwargs):
|
||||
"""
|
||||
Returns a list of lists pointing to layout objects of any type matching
|
||||
`LayoutClasses`::
|
||||
|
||||
[
|
||||
[[0,1,2], 'div'],
|
||||
[[0,3], 'field_name']
|
||||
]
|
||||
|
||||
:param max_level: An integer that indicates max level depth to reach when
|
||||
traversing a layout.
|
||||
: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)
|
||||
|
||||
pointers = []
|
||||
|
||||
if index is not None and not isinstance(index, list):
|
||||
index = [index]
|
||||
elif index is None:
|
||||
index = []
|
||||
|
||||
for i, layout_object in enumerate(self.fields):
|
||||
if isinstance(layout_object, LayoutClasses):
|
||||
if len(LayoutClasses) == 1 and LayoutClasses[0] == str:
|
||||
pointers.append([index + [i], layout_object])
|
||||
else:
|
||||
pointers.append([index + [i], layout_object.__class__.__name__.lower()])
|
||||
|
||||
# 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}
|
||||
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(
|
||||
render_field(field, form, form_style, context, template_pack=template_pack, **kwargs)
|
||||
for field in self.fields
|
||||
)
|
||||
|
||||
|
||||
class Layout(LayoutObject):
|
||||
"""
|
||||
Form Layout. It is conformed by Layout objects: `Fieldset`, `Row`, `Column`, `MultiField`,
|
||||
`HTML`, `ButtonHolder`, `Button`, `Hidden`, `Reset`, `Submit` and fields. Form fields
|
||||
have to be strings.
|
||||
Layout objects `Fieldset`, `Row`, `Column`, `MultiField` and `ButtonHolder` can hold other
|
||||
Layout objects within. Though `ButtonHolder` should only hold `HTML` and BaseInput
|
||||
inherited classes: `Button`, `Hidden`, `Reset` and `Submit`.
|
||||
|
||||
Example::
|
||||
|
||||
helper.layout = Layout(
|
||||
Fieldset('Company data',
|
||||
'is_company'
|
||||
),
|
||||
Fieldset(_('Contact details'),
|
||||
'email',
|
||||
Row('password1', 'password2'),
|
||||
'first_name',
|
||||
'last_name',
|
||||
HTML('<img src="/media/somepicture.jpg"/>'),
|
||||
'company'
|
||||
),
|
||||
ButtonHolder(
|
||||
Submit('Save', 'Save', css_class='button white'),
|
||||
),
|
||||
)
|
||||
"""
|
||||
|
||||
def __init__(self, *fields):
|
||||
self.fields = list(fields)
|
||||
|
||||
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
|
||||
return self.get_rendered_fields(form, form_style, context, template_pack, **kwargs)
|
||||
|
||||
|
||||
class ButtonHolder(LayoutObject):
|
||||
"""
|
||||
Layout object. It wraps fields in a <div class="buttonHolder">
|
||||
|
||||
This is where you should put Layout objects that render to form buttons like Submit.
|
||||
It should only hold `HTML` and `BaseInput` inherited objects.
|
||||
|
||||
Example::
|
||||
|
||||
ButtonHolder(
|
||||
HTML(<span style="display: hidden;">Information Saved</span>),
|
||||
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)
|
||||
|
||||
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})
|
||||
|
||||
return render_to_string(template, context.flatten())
|
||||
|
||||
|
||||
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.attrs = {}
|
||||
|
||||
if "css_class" in kwargs:
|
||||
self.field_classes += " %s" % kwargs.pop("css_class")
|
||||
|
||||
self.template = kwargs.pop("template", self.template)
|
||||
self.flat_attrs = flatatt(kwargs)
|
||||
|
||||
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
|
||||
"""
|
||||
Renders an `<input />` if container is used as a Layout object.
|
||||
Input button value can be a variable in context.
|
||||
"""
|
||||
self.value = Template(str(self.value)).render(context)
|
||||
template = self.get_template_name(template_pack)
|
||||
context.update({"input": self})
|
||||
|
||||
return render_to_string(template, context.flatten())
|
||||
|
||||
|
||||
class Submit(BaseInput):
|
||||
"""
|
||||
Used to create a Submit button descriptor for the {% crispy %} template tag::
|
||||
|
||||
submit = Submit('Search the Site', 'search this site')
|
||||
|
||||
.. note:: The first argument is also slugified and turned into the id for the submit button.
|
||||
"""
|
||||
|
||||
input_type = "submit"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.field_classes = "submit submitButton" if get_template_pack() == "uni_form" else "btn btn-primary"
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class Button(BaseInput):
|
||||
"""
|
||||
Used to create a Submit input descriptor for the {% crispy %} template tag::
|
||||
|
||||
button = Button('Button 1', 'Press Me!')
|
||||
|
||||
.. note:: The first argument is also slugified and turned into the id for the button.
|
||||
"""
|
||||
|
||||
input_type = "button"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.field_classes = "button" if get_template_pack() == "uni_form" else "btn"
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class Hidden(BaseInput):
|
||||
"""
|
||||
Used to create a Hidden input descriptor for the {% crispy %} template tag.
|
||||
"""
|
||||
|
||||
input_type = "hidden"
|
||||
field_classes = "hidden"
|
||||
|
||||
|
||||
class Reset(BaseInput):
|
||||
"""
|
||||
Used to create a Reset button input descriptor for the {% crispy %} template tag::
|
||||
|
||||
reset = Reset('Reset This Form', 'Revert Me!')
|
||||
|
||||
.. note:: The first argument is also slugified and turned into the id for the reset.
|
||||
"""
|
||||
|
||||
input_type = "reset"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.field_classes = "reset resetButton" if get_template_pack() == "uni_form" else "btn btn-inverse"
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class Fieldset(LayoutObject):
|
||||
"""
|
||||
Layout object. It wraps fields in a <fieldset>
|
||||
|
||||
Example::
|
||||
|
||||
Fieldset("Text for the legend",
|
||||
'form_field_1',
|
||||
'form_field_2'
|
||||
)
|
||||
|
||||
The first parameter is the text for the fieldset legend. This text is context aware,
|
||||
so you can do things like::
|
||||
|
||||
Fieldset("Data for {{ user.username }}",
|
||||
'form_field_1',
|
||||
'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.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 = ""
|
||||
if self.legend:
|
||||
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}
|
||||
)
|
||||
|
||||
|
||||
class MultiField(LayoutObject):
|
||||
""" MultiField container. Renders to a MultiField <div> """
|
||||
|
||||
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.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"]:
|
||||
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,
|
||||
)
|
||||
|
||||
template = self.get_template_name(template_pack)
|
||||
context.update({"multifield": self, "fields_output": fields_output})
|
||||
|
||||
return render_to_string(template, context.flatten())
|
||||
|
||||
|
||||
class Div(LayoutObject):
|
||||
"""
|
||||
Layout object. It wraps fields in a <div>
|
||||
|
||||
You can set `css_id` for a DOM id and `css_class` for a DOM class. Example::
|
||||
|
||||
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)
|
||||
|
||||
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})
|
||||
|
||||
|
||||
class Row(Div):
|
||||
"""
|
||||
Layout object. It wraps fields in a div whose default class is "formRow". Example::
|
||||
|
||||
Row('form_field_1', 'form_field_2', 'form_field_3')
|
||||
"""
|
||||
|
||||
template = "%s/layout/row.html"
|
||||
|
||||
|
||||
class Column(Div):
|
||||
"""
|
||||
Layout object. It wraps fields in a div so the wrapper can be used as a column. Example::
|
||||
|
||||
Column('form_field_1', 'form_field_2')
|
||||
|
||||
Depending on the template, css class associated to the div is formColumn, row, or nothing. For this last case, you
|
||||
must provide css classes. Example::
|
||||
|
||||
Column('form_field_1', 'form_field_2', css_class='col-xs-6',)
|
||||
"""
|
||||
|
||||
template = "%s/layout/column.html"
|
||||
|
||||
|
||||
class HTML:
|
||||
"""
|
||||
Layout object. It can contain pure HTML and it has access to the whole
|
||||
context of the page where the form is being rendered.
|
||||
|
||||
Examples::
|
||||
|
||||
HTML("{% if saved %}Data saved{% endif %}")
|
||||
HTML('<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" />')
|
||||
"""
|
||||
|
||||
def __init__(self, html):
|
||||
self.html = html
|
||||
|
||||
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs):
|
||||
return Template(str(self.html)).render(context)
|
||||
|
||||
|
||||
class Field(LayoutObject):
|
||||
"""
|
||||
Layout object, It contains one field name, and you can add attributes to it easily.
|
||||
For setting class attributes, you need to use `css_class`, as `class` is a Python keyword.
|
||||
|
||||
Example::
|
||||
|
||||
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"):
|
||||
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")
|
||||
else:
|
||||
self.attrs["class"] = kwargs.pop("css_class")
|
||||
|
||||
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()})
|
||||
|
||||
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
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
|
||||
class MultiWidgetField(Field):
|
||||
"""
|
||||
Layout object. For fields with :class:`~django.forms.MultiWidget` as `widget`, you can pass
|
||||
additional attributes to each widget.
|
||||
|
||||
Example::
|
||||
|
||||
MultiWidgetField(
|
||||
'multiwidget_field_name',
|
||||
attrs=(
|
||||
{'style': 'width: 30px;'},
|
||||
{'class': 'second_widget_class'}
|
||||
),
|
||||
)
|
||||
|
||||
.. 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)
|
||||
156
Lib/site-packages/crispy_forms/layout_slice.py
Normal file
156
Lib/site-packages/crispy_forms/layout_slice.py
Normal file
@@ -0,0 +1,156 @@
|
||||
from crispy_forms.bootstrap import Container
|
||||
from crispy_forms.exceptions import DynamicError
|
||||
from crispy_forms.layout import Fieldset, MultiField
|
||||
|
||||
|
||||
class LayoutSlice:
|
||||
# List of layout objects that need args passed first before fields
|
||||
args_first = (Fieldset, MultiField, Container)
|
||||
|
||||
def __init__(self, layout, key):
|
||||
self.layout = layout
|
||||
if isinstance(key, int):
|
||||
self.slice = slice(key, key + 1, 1)
|
||||
else:
|
||||
self.slice = key
|
||||
|
||||
def wrapped_object(self, LayoutClass, fields, *args, **kwargs):
|
||||
"""
|
||||
Returns a layout object of type `LayoutClass` with `args` and `kwargs` that
|
||||
wraps `fields` inside.
|
||||
"""
|
||||
if args:
|
||||
if isinstance(fields, list):
|
||||
fields = tuple(fields)
|
||||
else:
|
||||
fields = (fields,)
|
||||
|
||||
if LayoutClass in self.args_first:
|
||||
arguments = args + fields
|
||||
else:
|
||||
arguments = fields + args
|
||||
|
||||
return LayoutClass(*arguments, **kwargs)
|
||||
else:
|
||||
if isinstance(fields, list):
|
||||
return LayoutClass(*fields, **kwargs)
|
||||
else:
|
||||
return LayoutClass(fields, **kwargs)
|
||||
|
||||
def pre_map(self, function):
|
||||
"""
|
||||
Iterates over layout objects pointed in `self.slice` executing `function` on them.
|
||||
It passes `function` penultimate layout object and the position where to find last one
|
||||
"""
|
||||
if isinstance(self.slice, slice):
|
||||
for i in range(*self.slice.indices(len(self.layout.fields))):
|
||||
function(self.layout, i)
|
||||
|
||||
elif isinstance(self.slice, list):
|
||||
# A list of pointers Ex: [[[0, 0], 'div'], [[0, 2, 3], 'field_name']]
|
||||
for pointer in self.slice:
|
||||
position = pointer[0]
|
||||
|
||||
# If it's pointing first level
|
||||
if len(position) == 1:
|
||||
function(self.layout, position[-1])
|
||||
else:
|
||||
layout_object = self.layout.fields[position[0]]
|
||||
for i in position[1:-1]:
|
||||
layout_object = layout_object.fields[i]
|
||||
|
||||
try:
|
||||
function(layout_object, position[-1])
|
||||
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"
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
self.pre_map(wrap_object)
|
||||
|
||||
def wrap_once(self, LayoutClass, *args, **kwargs):
|
||||
"""
|
||||
Wraps every layout object pointed in `self.slice` under a `LayoutClass` instance with
|
||||
`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)
|
||||
|
||||
self.pre_map(wrap_object_once)
|
||||
|
||||
def wrap_together(self, LayoutClass, *args, **kwargs):
|
||||
"""
|
||||
Wraps all layout objects pointed in `self.slice` together under a `LayoutClass`
|
||||
instance with `args` and `kwargs` passed.
|
||||
"""
|
||||
if isinstance(self.slice, slice):
|
||||
# The start of the slice is replaced
|
||||
start = self.slice.start if self.slice.start is not None else 0
|
||||
self.layout.fields[start] = self.wrapped_object(
|
||||
LayoutClass, self.layout.fields[self.slice], *args, **kwargs
|
||||
)
|
||||
|
||||
# The rest of places of the slice are removed, as they are included in the previous
|
||||
for i in reversed(range(*self.slice.indices(len(self.layout.fields)))):
|
||||
if i != start:
|
||||
del self.layout.fields[i]
|
||||
|
||||
elif isinstance(self.slice, list):
|
||||
raise DynamicError("wrap_together doesn't work with filter, only with [] operator")
|
||||
|
||||
def map(self, function):
|
||||
"""
|
||||
Iterates over layout objects pointed in `self.slice` executing `function` on them
|
||||
It passes `function` last layout object
|
||||
"""
|
||||
if isinstance(self.slice, slice):
|
||||
for i in range(*self.slice.indices(len(self.layout.fields))):
|
||||
function(self.layout.fields[i])
|
||||
|
||||
elif isinstance(self.slice, list):
|
||||
# A list of pointers Ex: [[[0, 0], 'div'], [[0, 2, 3], 'field_name']]
|
||||
for pointer in self.slice:
|
||||
position = pointer[0]
|
||||
|
||||
layout_object = self.layout.fields[position[0]]
|
||||
for i in position[1:]:
|
||||
previous_layout_object = layout_object
|
||||
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):
|
||||
function(previous_layout_object)
|
||||
else:
|
||||
function(layout_object)
|
||||
|
||||
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")
|
||||
else:
|
||||
layout_object.attrs["class"] = kwargs.pop("css_class")
|
||||
layout_object.attrs.update(kwargs)
|
||||
|
||||
self.map(update_attrs)
|
||||
@@ -0,0 +1,10 @@
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" data-toggle="collapse" data-parent="#{{ div.data_parent }}" href="#{{ div.css_id }}">{{ div.name }}</a>
|
||||
</div>
|
||||
<div id="{{ div.css_id }}" class="accordion-body collapse{% if div.active %} in{% endif %}" >
|
||||
<div class="accordion-inner">
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="accordion" id="{{ accordion.css_id }}">
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,22 @@
|
||||
{% for fieldset in form.fieldsets %}
|
||||
<fieldset class="fieldset-{{ forloop.counter }} {{ fieldset.classes }}">
|
||||
{% if fieldset.legend %}
|
||||
<legend>{{ fieldset.legend }}</legend>
|
||||
{% endif %}
|
||||
|
||||
{% if fieldset.description %}
|
||||
<p class="description">{{ fieldset.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% for field in fieldset %}
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% include "bootstrap/field.html" %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if not forloop.last or not fieldset_open %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if form.form_html %}
|
||||
{% if include_media %}{{ form.media }}{% endif %}
|
||||
{% if form_show_errors %}
|
||||
{% include "bootstrap/errors.html" %}
|
||||
{% endif %}
|
||||
{{ form.form_html }}
|
||||
{% else %}
|
||||
{% include "bootstrap/uni_form.html" %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-block alert-error">
|
||||
{% if form_error_title %}<h4 class="alert-heading">{{ form_error_title }}</h4>{% endif %}
|
||||
<ul>
|
||||
{{ form.non_field_errors|unordered_list }}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if formset.non_form_errors %}
|
||||
<div class="alert alert-block alert-error">
|
||||
{% if formset_error_title %}<h4 class="alert-heading">{{ formset_error_title }}</h4>{% endif %}
|
||||
<ul>
|
||||
{{ formset.non_form_errors|unordered_list }}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
<{% if tag %}{{ tag }}{% else %}div{% endif %} id="div_{{ field.auto_id }}" class="control-group{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if form_show_errors%}{% if field.errors %} error{% endif %}{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
{% if field.label and not field|is_checkbox and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="control-label {% if field.field.required %}requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_checkboxselectmultiple %}
|
||||
{% include 'bootstrap/layout/checkboxselectmultiple.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_radioselect %}
|
||||
{% include 'bootstrap/layout/radioselect.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
|
||||
<div class="controls">
|
||||
{% if field|is_checkbox and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="checkbox {% if field.field.required %}requiredField{% endif %}">
|
||||
{% crispy_field field %}
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% include 'bootstrap/layout/help_text_and_errors.html' %}
|
||||
{% else %}
|
||||
{% crispy_field field %}
|
||||
{% include 'bootstrap/layout/help_text_and_errors.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</{% if tag %}{{ tag }}{% else %}div{% endif %}>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,4 @@
|
||||
<div{% if alert.css_id %} id="{{ alert.css_id }}"{% endif %}{% if alert.css_class %} class="{{ alert.css_class }}"{% endif %}>
|
||||
{% if dismiss %}<button type="button" class="close" data-dismiss="alert">×</button>{% endif %}
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<input type="{{ input.input_type }}"
|
||||
name="{% if input.name|wordcount > 1 %}{{ input.name|slugify }}{% else %}{{ input.name }}{% endif %}"
|
||||
value="{{ input.value }}"
|
||||
{% if input.input_type != "hidden" %}
|
||||
class="{{ input.field_classes }}"
|
||||
id="{% if input.id %}{{ input.id }}{% else %}{{ input.input_type }}-id-{{ input.name|slugify }}{% endif %}"
|
||||
{% endif %}
|
||||
{{ input.flat_attrs|safe }}
|
||||
/>
|
||||
@@ -0,0 +1 @@
|
||||
<button {{ button.flat_attrs|safe }}>{{ button.content|safe }}</button>
|
||||
@@ -0,0 +1,4 @@
|
||||
<div {% if buttonholder.css_id %}id="{{ buttonholder.css_id }}"{% endif %}
|
||||
class="buttonHolder{% if buttonholder.css_class %} {{ buttonholder.css_class }}{% endif %}">
|
||||
{{ fields_output|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
{% load crispy_forms_filters %}
|
||||
{% load l10n %}
|
||||
|
||||
<div class="controls"{% if flat_attrs %} {{ flat_attrs|safe }}{% endif %}>
|
||||
{% include 'bootstrap/layout/field_errors_block.html' %}
|
||||
|
||||
{% for choice in field.field.choices %}
|
||||
<label class="checkbox{% if inline_class %} {{ inline_class }}{% endif %}" for="id_{{ field.html_name }}_{{ forloop.counter }}">
|
||||
<input type="checkbox"{% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|default_if_none:""|stringformat:"s" %} checked="checked"{% endif %} name="{{ field.html_name }}" id="id_{{ field.html_name }}_{{ forloop.counter }}" value="{{ choice.0|unlocalize }}" {{ field.field.widget.attrs|flatatt }}>{{ choice.1|unlocalize }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
|
||||
{% include 'bootstrap/layout/help_text.html' %}
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
<div id="div_{{ field.auto_id }}" class="control-group{% if form_show_errors and field.errors %} error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
|
||||
{% if field.label %}
|
||||
<label for="{{ field.auto_id }}" class="control-label{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% include 'bootstrap/layout/checkboxselectmultiple.html' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
<div {% if div.css_id %}id="{{ div.css_id }}"{% endif %} class="{{ div.css_class|default:'' }}" {{ div.flat_attrs|safe }}>
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,4 @@
|
||||
<div {% if div.css_id %}id="{{ div.css_id }}"{% endif %}
|
||||
{% if div.css_class %}class="{{ div.css_class }}"{% endif %} {{ div.flat_attrs|safe }}>
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,5 @@
|
||||
{% if form_show_errors and field.errors %}
|
||||
{% for error in field.errors %}
|
||||
<span id="error_{{ forloop.counter }}_{{ field.auto_id }}" class="help-inline"><strong>{{ error }}</strong></span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,5 @@
|
||||
{% if form_show_errors and field.errors %}
|
||||
{% for error in field.errors %}
|
||||
<p id="error_{{ forloop.counter }}_{{ field.auto_id }}" class="help-block"><strong>{{ error }}</strong></p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,17 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
<div{% if div.css_id %} id="{{ div.css_id }}"{% endif %} class="control-group{% if form_show_errors and field.errors %} error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}{% if div.css_class %} {{ div.css_class }}{% endif %}" {{ div.flat_attrs|safe }}>
|
||||
{% if field.label and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="control-label{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
{% crispy_field field %}
|
||||
{{ buttons|safe }}
|
||||
</div>
|
||||
{% include 'bootstrap/layout/help_text_and_errors.html' %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
<fieldset {% if fieldset.css_id %}id="{{ fieldset.css_id }}"{% endif %}
|
||||
{% if fieldset.css_class or form_style %}class="{{ fieldset.css_class }} {{ form_style }}"{% endif %}
|
||||
{{ fieldset.flat_attrs|safe }}>
|
||||
{% if legend %}<legend>{{ legend|safe }}</legend>{% endif %}
|
||||
{{ fields|safe }}
|
||||
</fieldset>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div{% if formactions.attrs %} {{ formactions.flat_attrs|safe }}{% endif %} class="form-actions">
|
||||
{{ fields_output|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
{% if field.help_text %}
|
||||
{% if help_text_inline %}
|
||||
<span id="hint_{{ field.auto_id }}" class="help-inline">{{ field.help_text|safe }}</span>
|
||||
{% else %}
|
||||
<p id="hint_{{ field.auto_id }}" class="help-block">{{ field.help_text|safe }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,13 @@
|
||||
{% if help_text_inline and not error_text_inline %}
|
||||
{% include 'bootstrap/layout/help_text.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if error_text_inline %}
|
||||
{% include 'bootstrap/layout/field_errors.html' %}
|
||||
{% else %}
|
||||
{% include 'bootstrap/layout/field_errors_block.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if not help_text_inline %}
|
||||
{% include 'bootstrap/layout/help_text.html' %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,27 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
|
||||
{% if field.label %}
|
||||
<label for="{{ field.id_for_label }}"{% if labelclass %} class="{{ labelclass }}"{% endif %}>
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_checkbox %}
|
||||
{% crispy_field field %}
|
||||
{% endif %}
|
||||
|
||||
{% if field.label %}
|
||||
{{ field.label }}
|
||||
{% endif %}
|
||||
|
||||
{% if not field|is_checkbox %}
|
||||
{% crispy_field field %}
|
||||
{% endif %}
|
||||
|
||||
{% if field.label %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
@@ -0,0 +1,24 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
<div id="div_{{ field.auto_id }}" class="control-group{% if form_show_errors and field.errors %} error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
|
||||
{% if field.label and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="control-label{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<div class="controls">
|
||||
<div class="{% if crispy_prepended_text %}input-prepend{% endif %} {% if crispy_appended_text %}input-append{% endif %}">
|
||||
{% if crispy_prepended_text %}<span class="{% if not field|is_select %}add-on{% endif %}{% if active %} active{% endif %}">{{ crispy_prepended_text|safe }}</span>{% endif %}
|
||||
{% crispy_field field %}
|
||||
{% if crispy_appended_text %}<span class="{% if not field|is_select %}add-on{% endif %}{% if active %} active{% endif %}">{{ crispy_appended_text|safe }}</span>{% endif %}
|
||||
</div>
|
||||
|
||||
{% include 'bootstrap/layout/help_text_and_errors.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,14 @@
|
||||
{% load crispy_forms_filters %}
|
||||
{% load l10n %}
|
||||
|
||||
<div class="controls"{% if flat_attrs %} {{ flat_attrs|safe }}{% endif %}>
|
||||
{% include 'bootstrap/layout/field_errors_block.html' %}
|
||||
|
||||
{% for choice in field.field.choices %}
|
||||
<label for="id_{{ field.html_name }}_{{ forloop.counter }}" class="radio{% if inline_class %} {{ inline_class }}{% endif %}">
|
||||
<input type="radio"{% if choice.0|stringformat:"s" == field.value|default_if_none:""|stringformat:"s" %} checked="checked"{% endif %} name="{{ field.html_name }}" id="id_{{ field.html_name }}_{{ forloop.counter }}" value="{{ choice.0|unlocalize }}" {{ field.field.widget.attrs|flatatt }}>{{ choice.1|unlocalize }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
|
||||
{% include 'bootstrap/layout/help_text.html' %}
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
<div id="div_{{ field.auto_id }}" class="control-group{% if form_show_errors and field.errors %} error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
|
||||
{% if field.label %}
|
||||
<label for="{{ field.auto_id }}" class="control-label{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% include 'bootstrap/layout/radioselect.html' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
<div {% if div.css_id %}id="{{ div.css_id }}"{% endif %} class="row {{ div.css_class|default:'' }}" {{ div.flat_attrs|safe }}>
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<li class="tab-pane{% if 'active' in link.css_class %} active{% endif %}"><a href="#{{ link.css_id }}" data-toggle="tab">{{ link.name|capfirst }}{% if tab.errors %}!{% endif %}</a></li>
|
||||
@@ -0,0 +1,6 @@
|
||||
<ul{% if tabs.css_id %} id="{{ tabs.css_id }}"{% endif %} class="nav nav-tabs">
|
||||
{{ links|safe }}
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
<div id="div_{{ field.auto_id }}" class="control-group{% if form_show_errors and field.errors %} error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
<div class="control-label{% if field.field.required %} requiredField{% endif %}">{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}</div>
|
||||
<div class="controls">
|
||||
<span {{ flat_attrs|safe }}>{% if field.value %}{{ field.value }}{% endif %}</span>
|
||||
{% include 'bootstrap/layout/help_text.html' %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,62 @@
|
||||
{% load crispy_forms_tags %}
|
||||
{% load crispy_forms_utils %}
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% specialspaceless %}
|
||||
{% if formset_tag %}
|
||||
<form {{ flat_attrs|safe }} method="{{ form_method }}" {% if formset.is_multipart %} enctype="multipart/form-data"{% endif %}>
|
||||
{% endif %}
|
||||
{% if formset_method|lower == 'post' and not disable_csrf %}
|
||||
{% csrf_token %}
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{{ formset.management_form|crispy }}
|
||||
</div>
|
||||
|
||||
<table{% if form_id %} id="{{ form_id }}_table"{% endif%} class="table table-striped table-condensed">
|
||||
<thead>
|
||||
{% if formset.readonly and not formset.queryset.exists %}
|
||||
{% else %}
|
||||
<tr>
|
||||
{% for field in formset.forms.0 %}
|
||||
{% if field.label and not field.is_hidden %}
|
||||
<th for="{{ field.auto_id }}" class="control-label {% if field.field.required and not field|is_checkbox %}requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required and not field|is_checkbox %}<span class="asteriskField">*</span>{% endif %}
|
||||
</th>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr class="hidden empty-form">
|
||||
{% for field in formset.empty_form %}
|
||||
{% include 'bootstrap/field.html' with tag="td" form_show_labels=False %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
{% for form in formset %}
|
||||
{% if form_show_errors and not form.is_extra %}
|
||||
{% include "bootstrap/errors.html" %}
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
{% for field in form %}
|
||||
{% include 'bootstrap/field.html' with tag="td" form_show_labels=False %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% if inputs %}
|
||||
<div class="form-actions">
|
||||
{% for input in inputs %}
|
||||
{% include "bootstrap/layout/baseinput.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if formset_tag %}</form>{% endif %}
|
||||
{% endspecialspaceless %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% load crispy_forms_utils %}
|
||||
|
||||
{% specialspaceless %}
|
||||
{% if include_media %}{{ form.media }}{% endif %}
|
||||
{% if form_show_errors %}
|
||||
{% include "bootstrap/errors.html" %}
|
||||
{% endif %}
|
||||
{% for field in form %}
|
||||
{% include field_template %}
|
||||
{% endfor %}
|
||||
{% endspecialspaceless %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% with formset.management_form as form %}
|
||||
{% include 'bootstrap/uni_form.html' %}
|
||||
{% endwith %}
|
||||
{% for form in formset %}
|
||||
<div class="multiField">
|
||||
{% include 'bootstrap/uni_form.html' %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,19 @@
|
||||
{% load crispy_forms_utils %}
|
||||
|
||||
{% specialspaceless %}
|
||||
{% if form_tag %}<form {{ flat_attrs|safe }} method="{{ form_method }}" {% if form.is_multipart %} enctype="multipart/form-data"{% endif %}>{% endif %}
|
||||
{% if form_method|lower == 'post' and not disable_csrf %}
|
||||
{% csrf_token %}
|
||||
{% endif %}
|
||||
|
||||
{% include "bootstrap/display_form.html" %}
|
||||
|
||||
{% if inputs %}
|
||||
<div class="form-actions">
|
||||
{% for input in inputs %}
|
||||
{% include "bootstrap/layout/baseinput.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if form_tag %}</form>{% endif %}
|
||||
{% endspecialspaceless %}
|
||||
@@ -0,0 +1,30 @@
|
||||
{% load crispy_forms_tags %}
|
||||
{% load crispy_forms_utils %}
|
||||
|
||||
{% specialspaceless %}
|
||||
{% if formset_tag %}
|
||||
<form {{ flat_attrs|safe }} method="{{ form_method }}" {% if formset.is_multipart %} enctype="multipart/form-data"{% endif %}>
|
||||
{% endif %}
|
||||
{% if formset_method|lower == 'post' and not disable_csrf %}
|
||||
{% csrf_token %}
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{{ formset.management_form|crispy }}
|
||||
</div>
|
||||
|
||||
{% include "bootstrap/errors_formset.html" %}
|
||||
|
||||
{% for form in formset %}
|
||||
{% include "bootstrap/display_form.html" %}
|
||||
{% endfor %}
|
||||
|
||||
{% if inputs %}
|
||||
<div class="form-actions">
|
||||
{% for input in inputs %}
|
||||
{% include "bootstrap/layout/baseinput.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if formset_tag %}</form>{% endif %}
|
||||
{% endspecialspaceless %}
|
||||
@@ -0,0 +1,12 @@
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a class="accordion-toggle" data-toggle="collapse" data-parent="#{{ div.data_parent }}" href="#{{ div.css_id }}">{{ div.name }}</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="{{ div.css_id }}" class="panel-collapse collapse{% if div.active %} in{% endif %}" >
|
||||
<div class="panel-body">
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="panel-group" id="{{ accordion.css_id }}">
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,22 @@
|
||||
{% for fieldset in form.fieldsets %}
|
||||
<fieldset class="fieldset-{{ forloop.counter }} {{ fieldset.classes }}">
|
||||
{% if fieldset.legend %}
|
||||
<legend>{{ fieldset.legend }}</legend>
|
||||
{% endif %}
|
||||
|
||||
{% if fieldset.description %}
|
||||
<p class="description">{{ fieldset.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% for field in fieldset %}
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% include "bootstrap3/field.html" %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if not forloop.last or not fieldset_open %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if form.form_html %}
|
||||
{% if include_media %}{{ form.media }}{% endif %}
|
||||
{% if form_show_errors %}
|
||||
{% include "bootstrap3/errors.html" %}
|
||||
{% endif %}
|
||||
{{ form.form_html }}
|
||||
{% else %}
|
||||
{% include "bootstrap3/uni_form.html" %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-block alert-danger">
|
||||
{% if form_error_title %}<h4 class="alert-heading">{{ form_error_title }}</h4>{% endif %}
|
||||
<ul>
|
||||
{{ form.non_field_errors|unordered_list }}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if formset.non_form_errors %}
|
||||
<div class="alert alert-block alert-danger">
|
||||
{% if formset_error_title %}<h4 class="alert-heading">{{ formset_error_title }}</h4>{% endif %}
|
||||
<ul>
|
||||
{{ formset.non_form_errors|unordered_list }}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% if field|is_checkbox %}
|
||||
<div class="form-group">
|
||||
{% if label_class %}
|
||||
<div class="controls {% for offset in bootstrap_checkbox_offsets %}{{ offset }} {% endfor %}{{ field_class }}">
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<{% if tag %}{{ tag }}{% else %}div{% endif %} id="div_{{ field.auto_id }}" {% if not field|is_checkbox %}class="form-group{% else %}class="checkbox{% endif %}{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if form_show_errors%}{% if field.errors %} has-error{% endif %}{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
{% if field.label and not field|is_checkbox and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_checkboxselectmultiple %}
|
||||
{% include 'bootstrap3/layout/checkboxselectmultiple.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_radioselect %}
|
||||
{% include 'bootstrap3/layout/radioselect.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
|
||||
{% if field|is_checkbox and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="{% if field.field.required %} requiredField{% endif %}">
|
||||
{% crispy_field field %}
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% include 'bootstrap3/layout/help_text_and_errors.html' %}
|
||||
{% else %}
|
||||
<div class="controls {{ field_class }}">
|
||||
{% crispy_field field %}
|
||||
{% include 'bootstrap3/layout/help_text_and_errors.html' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</{% if tag %}{{ tag }}{% else %}div{% endif %}>
|
||||
{% if field|is_checkbox %}
|
||||
{% if label_class %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,13 @@
|
||||
{% if inputs %}
|
||||
<div class="form-group">
|
||||
{% if label_class %}
|
||||
<div class="aab controls {{ label_class }}"></div>
|
||||
{% endif %}
|
||||
|
||||
<div class="controls {{ field_class }}">
|
||||
{% for input in inputs %}
|
||||
{% include "bootstrap3/layout/baseinput.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,4 @@
|
||||
<div{% if alert.css_id %} id="{{ alert.css_id }}"{% endif %}{% if alert.css_class %} class="{{ alert.css_class }}"{% endif %}>
|
||||
{% if dismiss %}<button type="button" class="close" data-dismiss="alert">×</button>{% endif %}
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<input type="{{ input.input_type }}"
|
||||
name="{% if input.name|wordcount > 1 %}{{ input.name|slugify }}{% else %}{{ input.name }}{% endif %}"
|
||||
value="{{ input.value }}"
|
||||
{% if input.input_type != "hidden" %}
|
||||
class="{{ input.field_classes }}"
|
||||
id="{% if input.id %}{{ input.id }}{% else %}{{ input.input_type }}-id-{{ input.name|slugify }}{% endif %}"
|
||||
{% endif %}
|
||||
{{ input.flat_attrs|safe }}
|
||||
/>
|
||||
@@ -0,0 +1 @@
|
||||
<button {{ button.flat_attrs|safe }}>{{ button.content|safe }}</button>
|
||||
@@ -0,0 +1,4 @@
|
||||
<div {% if buttonholder.css_id %}id="{{ buttonholder.css_id }}"{% endif %}
|
||||
class="buttonHolder{% if buttonholder.css_class %} {{ buttonholder.css_class }}{% endif %}">
|
||||
{{ fields_output|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
{% load crispy_forms_filters %}
|
||||
{% load l10n %}
|
||||
|
||||
<div class="controls {{ field_class }}"{% if flat_attrs %} {{ flat_attrs|safe }}{% endif %}>
|
||||
{% include 'bootstrap3/layout/field_errors_block.html' %}
|
||||
|
||||
{% for choice in field.field.choices %}
|
||||
|
||||
{% if not inline_class %}<div class="checkbox">{% endif %}
|
||||
<label class="{% if inline_class %}checkbox-{{ inline_class }}{% endif %}" for="id_{{ field.html_name }}_{{ forloop.counter }}">
|
||||
<input type="checkbox"{% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|default_if_none:""|stringformat:"s" %} checked="checked"{% endif %} name="{{ field.html_name }}" id="id_{{ field.html_name }}_{{ forloop.counter }}" value="{{ choice.0|unlocalize }}" {{ field.field.widget.attrs|flatatt }}>{{ choice.1|unlocalize }}
|
||||
</label>
|
||||
{% if not inline_class %}</div>{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% include 'bootstrap3/layout/help_text.html' %}
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
<div id="div_{{ field.auto_id }}" class="form-group{% if form_show_errors and field.errors %} has-error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
|
||||
{% if field.label %}
|
||||
<label for="{{ field.auto_id }}" class="control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% include 'bootstrap3/layout/checkboxselectmultiple.html' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
<div {% if div.css_id %}id="{{ div.css_id }}"{% endif %} class="formColumn {{ div.css_class|default:'' }}" {{ div.flat_attrs|safe }}>
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,4 @@
|
||||
<div {% if div.css_id %}id="{{ div.css_id }}"{% endif %}
|
||||
{% if div.css_class %}class="{{ div.css_class }}"{% endif %} {{ div.flat_attrs|safe }}>
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,5 @@
|
||||
{% if form_show_errors and field.errors %}
|
||||
{% for error in field.errors %}
|
||||
<span id="error_{{ forloop.counter }}_{{ field.auto_id }}" class="help-block"><strong>{{ error }}</strong></span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,5 @@
|
||||
{% if form_show_errors and field.errors %}
|
||||
{% for error in field.errors %}
|
||||
<p id="error_{{ forloop.counter }}_{{ field.auto_id }}" class="help-block"><strong>{{ error }}</strong></p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,17 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
<div{% if div.css_id %} id="{{ div.css_id }}"{% endif %} class="form-group{% if form_show_errors and field.errors %} has-error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}{% if div.css_class %} {{ div.css_class }}{% endif %}" {{ div.flat_attrs|safe }}>
|
||||
{% if field.label and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<div class="controls {{ field_class }}">
|
||||
<div class="input-group">
|
||||
{% crispy_field field %}
|
||||
<span class="input-group-btn{% if active %} active{% endif %}{% if input_size %} {{ input_size }}{% endif %}">{{ buttons|safe }}</span>
|
||||
</div>
|
||||
{% include 'bootstrap3/layout/help_text_and_errors.html' %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
<fieldset {% if fieldset.css_id %}id="{{ fieldset.css_id }}"{% endif %}
|
||||
{% if fieldset.css_class or form_style %}class="{{ fieldset.css_class }} {{ form_style }}"{% endif %}
|
||||
{{ fieldset.flat_attrs|safe }}>
|
||||
{% if legend %}<legend>{{ legend|safe }}</legend>{% endif %}
|
||||
{{ fields|safe }}
|
||||
</fieldset>
|
||||
@@ -0,0 +1,9 @@
|
||||
<div{% if formactions.attrs %} {{ formactions.flat_attrs|safe }}{% endif %} class="form-group">
|
||||
{% if label_class %}
|
||||
<div class="aab controls {{ label_class }}"></div>
|
||||
{% endif %}
|
||||
|
||||
<div class="controls {{ field_class }}">
|
||||
{{ fields_output|safe }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
{% if field.help_text %}
|
||||
{% if help_text_inline %}
|
||||
<span id="hint_{{ field.auto_id }}" class="help-block">{{ field.help_text|safe }}</span>
|
||||
{% else %}
|
||||
<div id="hint_{{ field.auto_id }}" class="help-block">{{ field.help_text|safe }}</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,13 @@
|
||||
{% if help_text_inline and not error_text_inline %}
|
||||
{% include 'bootstrap3/layout/help_text.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if error_text_inline %}
|
||||
{% include 'bootstrap3/layout/field_errors.html' %}
|
||||
{% else %}
|
||||
{% include 'bootstrap3/layout/field_errors_block.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if not help_text_inline %}
|
||||
{% include 'bootstrap3/layout/help_text.html' %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,21 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% if field|is_checkbox %}
|
||||
<div id="div_{{ field.auto_id }}" class="checkbox{% if wrapper_class %} {{ wrapper_class }}{% endif %}">
|
||||
<label for="{{ field.id_for_label }}" class="{% if field.field.required %} requiredField{% endif %}">
|
||||
{% crispy_field field 'class' 'checkbox' %}
|
||||
{{ field.label|safe }}
|
||||
</label>
|
||||
</div>
|
||||
{% else %}
|
||||
<div id="div_{{ field.auto_id }}" class="form-group{% if wrapper_class %} {{ wrapper_class }}{% endif %}">
|
||||
<label for="{{ field.id_for_label }}" class="sr-only{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}
|
||||
</label>
|
||||
{% crispy_field field 'placeholder' field.label %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,25 @@
|
||||
<div {% if multifield.css_id or errors %}id="{{ multifield.css_id }}"{% endif %}
|
||||
{% if multifield.css_class %}class="{{ multifield.css_class }}"{% endif %}
|
||||
{{ multifield.flat_attrs|safe }}>
|
||||
|
||||
{% if form_show_errors %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{% for field in multifield.bound_fields %}
|
||||
{% if field.errors %}
|
||||
{% for error in field.errors %}
|
||||
<p id="error_{{ forloop.counter }}_{{ field.auto_id }}">{{ error }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if multifield.label_html %}
|
||||
<p {% if multifield.label_class %}class="{{ multifield.label_class }}"{% endif %}>{{ multifield.label_html|safe }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="multiField">
|
||||
{{ fields_output|safe }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,24 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
<div id="div_{{ field.auto_id }}" class="form-group{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if form_show_errors and field.errors %} has-error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
|
||||
{% if field.label and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<div class="controls {{ field_class }}">
|
||||
<div class="input-group">
|
||||
{% if crispy_prepended_text %}<span class="input-group-addon{% if active %} active{% endif %}{% if input_size %} {{ input_size }}{% endif %}">{{ crispy_prepended_text|safe }}</span>{% endif %}
|
||||
{% crispy_field field %}
|
||||
{% if crispy_appended_text %}<span class="input-group-addon{% if active %} active{% endif %}{% if input_size %} {{ input_size }}{% endif %}">{{ crispy_appended_text|safe }}</span>{% endif %}
|
||||
</div>
|
||||
|
||||
{% include 'bootstrap3/layout/help_text_and_errors.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,16 @@
|
||||
{% load crispy_forms_filters %}
|
||||
{% load l10n %}
|
||||
|
||||
<div class="controls {{ field_class }}"{% if flat_attrs %} {{ flat_attrs|safe }}{% endif %}>
|
||||
{% include 'bootstrap3/layout/field_errors_block.html' %}
|
||||
|
||||
{% for choice in field.field.choices %}
|
||||
{% if not inline_class %}<div class="radio">{% endif %}
|
||||
<label for="id_{{ field.html_name }}_{{ forloop.counter }}" class="{% if inline_class %}radio-{{ inline_class }}{% endif %}">
|
||||
<input type="radio"{% if choice.0|stringformat:"s" == field.value|default_if_none:""|stringformat:"s" %} checked="checked"{% endif %} name="{{ field.html_name }}" id="id_{{ field.html_name }}_{{ forloop.counter }}" value="{{ choice.0|unlocalize }}" {{ field.field.widget.attrs|flatatt }}>{{ choice.1|unlocalize }}
|
||||
</label>
|
||||
{% if not inline_class %}</div>{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% include 'bootstrap3/layout/help_text.html' %}
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
<div id="div_{{ field.auto_id }}" class="form-group{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if form_show_errors and field.errors %} has-error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
|
||||
{% if field.label %}
|
||||
<label for="{{ field.auto_id }}" class="control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% include 'bootstrap3/layout/radioselect.html' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
<div {% if div.css_id %}id="{{ div.css_id }}"{% endif %} class="row {{ div.css_class|default:'' }}" {{ div.flat_attrs|safe }}>
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<li class="tab-pane{% if 'active' in link.css_class %} active{% endif %}"><a href="#{{ link.css_id }}" data-toggle="tab">{{ link.name|capfirst }}{% if tab.errors %}!{% endif %}</a></li>
|
||||
@@ -0,0 +1,6 @@
|
||||
<ul{% if tabs.css_id %} id="{{ tabs.css_id }}"{% endif %} class="nav nav-tabs">
|
||||
{{ links|safe }}
|
||||
</ul>
|
||||
<div class="tab-content panel-body">
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,10 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
|
||||
<div id="div_{{ field.auto_id }}" class="form-group{% if form_show_errors and field.errors %} error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
<label class="control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}</label>
|
||||
<div class="controls {{ field_class }}">
|
||||
{% crispy_field field 'disabled' 'disabled' %}
|
||||
{% include 'bootstrap3/layout/help_text.html' %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,39 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
|
||||
{% if field|is_checkbox %}
|
||||
{% if field.errors %}<div class="has-error">{% endif %}
|
||||
<div class="checkbox">
|
||||
{% if field.label %}
|
||||
<label for="{{ field.id_for_label }}"{% if labelclass %} class="{{ labelclass }}"{% endif %}>
|
||||
{% endif %}
|
||||
|
||||
{% crispy_field field %}
|
||||
{{ field.label }}
|
||||
|
||||
{% if field.label %}
|
||||
</label>
|
||||
{% endif %}
|
||||
{% if field.help_text %}
|
||||
<p id="help_{{ field.auto_id }}" class="help-block">{{ field.help_text|safe }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if field.errors %}</div>{% endif %}
|
||||
{% else %}
|
||||
<div class="form-group {% if field.errors %}has-error{% endif %}">
|
||||
{% if field.label %}
|
||||
<label class="control-label" for="{{ field.id_for_label }}"{% if labelclass %} class="{{ labelclass }}"{% endif %}>
|
||||
{{ field.label }}
|
||||
</label>
|
||||
{% endif %}
|
||||
{% crispy_field field %}
|
||||
{% if field.help_text %}
|
||||
<span id="help_{{ field.auto_id }}" class="help-block">{{ field.help_text|safe }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
@@ -0,0 +1,57 @@
|
||||
{% load crispy_forms_tags %}
|
||||
{% load crispy_forms_utils %}
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% specialspaceless %}
|
||||
{% if formset_tag %}
|
||||
<form {{ flat_attrs|safe }} method="{{ form_method }}" {% if formset.is_multipart %} enctype="multipart/form-data"{% endif %}>
|
||||
{% endif %}
|
||||
{% if formset_method|lower == 'post' and not disable_csrf %}
|
||||
{% csrf_token %}
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{{ formset.management_form|crispy }}
|
||||
</div>
|
||||
|
||||
<table{% if form_id %} id="{{ form_id }}_table"{% endif%} class="table table-striped table-condensed">
|
||||
<thead>
|
||||
{% if formset.readonly and not formset.queryset.exists %}
|
||||
{% else %}
|
||||
<tr>
|
||||
{% for field in formset.forms.0 %}
|
||||
{% if field.label and not field.is_hidden %}
|
||||
<th for="{{ field.auto_id }}" class="control-label {% if field.field.required %}requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required and not field|is_checkbox %}<span class="asteriskField">*</span>{% endif %}
|
||||
</th>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr class="hidden empty-form">
|
||||
{% for field in formset.empty_form %}
|
||||
{% include 'bootstrap3/field.html' with tag="td" form_show_labels=False %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
{% for form in formset %}
|
||||
{% if form_show_errors and not form.is_extra %}
|
||||
{% include "bootstrap3/errors.html" %}
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
{% for field in form %}
|
||||
{% include 'bootstrap3/field.html' with tag="td" form_show_labels=False %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% include "bootstrap3/inputs.html" %}
|
||||
|
||||
{% if formset_tag %}</form>{% endif %}
|
||||
{% endspecialspaceless %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% load crispy_forms_utils %}
|
||||
|
||||
{% specialspaceless %}
|
||||
{% if include_media %}{{ form.media }}{% endif %}
|
||||
{% if form_show_errors %}
|
||||
{% include "bootstrap3/errors.html" %}
|
||||
{% endif %}
|
||||
{% for field in form %}
|
||||
{% include field_template %}
|
||||
{% endfor %}
|
||||
{% endspecialspaceless %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% with formset.management_form as form %}
|
||||
{% include 'bootstrap3/uni_form.html' %}
|
||||
{% endwith %}
|
||||
{% for form in formset %}
|
||||
<div class="multiField">
|
||||
{% include 'bootstrap3/uni_form.html' %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,14 @@
|
||||
{% load crispy_forms_utils %}
|
||||
|
||||
{% specialspaceless %}
|
||||
{% if form_tag %}<form {{ flat_attrs|safe }} method="{{ form_method }}" {% if form.is_multipart %} enctype="multipart/form-data"{% endif %}>{% endif %}
|
||||
{% if form_method|lower == 'post' and not disable_csrf %}
|
||||
{% csrf_token %}
|
||||
{% endif %}
|
||||
|
||||
{% include "bootstrap3/display_form.html" %}
|
||||
|
||||
{% include "bootstrap3/inputs.html" %}
|
||||
|
||||
{% if form_tag %}</form>{% endif %}
|
||||
{% endspecialspaceless %}
|
||||
@@ -0,0 +1,30 @@
|
||||
{% load crispy_forms_tags %}
|
||||
{% load crispy_forms_utils %}
|
||||
|
||||
{% specialspaceless %}
|
||||
{% if formset_tag %}
|
||||
<form {{ flat_attrs|safe }} method="{{ form_method }}" {% if formset.is_multipart %} enctype="multipart/form-data"{% endif %}>
|
||||
{% endif %}
|
||||
{% if formset_method|lower == 'post' and not disable_csrf %}
|
||||
{% csrf_token %}
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{{ formset.management_form|crispy }}
|
||||
</div>
|
||||
|
||||
{% include "bootstrap3/errors_formset.html" %}
|
||||
|
||||
{% for form in formset %}
|
||||
{% include "bootstrap3/display_form.html" %}
|
||||
{% endfor %}
|
||||
|
||||
{% if inputs %}
|
||||
<div class="form-actions">
|
||||
{% for input in inputs %}
|
||||
{% include "bootstrap3/layout/baseinput.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if formset_tag %}</form>{% endif %}
|
||||
{% endspecialspaceless %}
|
||||
@@ -0,0 +1,17 @@
|
||||
<div class="card mb-2">
|
||||
<div class="card-header" role="tab">
|
||||
<h5 class="mb-0">
|
||||
<a data-toggle="collapse" href="#{{ div.css_id }}" aria-expanded="true"
|
||||
aria-controls="{{ div.css_id }}">
|
||||
{{ div.name }}
|
||||
</a>
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div id="{{ div.css_id }}" class="collapse{% if div.active %} show{% endif %}" role="tabpanel"
|
||||
aria-labelledby="{{ div.css_id }}" data-parent="#accordion">
|
||||
<div class="card-body">
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div id="accordion" role="tablist">
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,22 @@
|
||||
{% for fieldset in form.fieldsets %}
|
||||
<fieldset class="fieldset-{{ forloop.counter }} {{ fieldset.classes }}">
|
||||
{% if fieldset.legend %}
|
||||
<legend>{{ fieldset.legend }}</legend>
|
||||
{% endif %}
|
||||
|
||||
{% if fieldset.description %}
|
||||
<p class="description">{{ fieldset.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% for field in fieldset %}
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% include "bootstrap4/field.html" %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if not forloop.last or not fieldset_open %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if form.form_html %}
|
||||
{% if include_media %}{{ form.media }}{% endif %}
|
||||
{% if form_show_errors %}
|
||||
{% include "bootstrap4/errors.html" %}
|
||||
{% endif %}
|
||||
{{ form.form_html }}
|
||||
{% else %}
|
||||
{% include "bootstrap4/uni_form.html" %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-block alert-danger">
|
||||
{% if form_error_title %}<h4 class="alert-heading">{{ form_error_title }}</h4>{% endif %}
|
||||
<ul class="m-0">
|
||||
{{ form.non_field_errors|unordered_list }}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if formset.non_form_errors %}
|
||||
<div class="alert alert-block alert-danger">
|
||||
{% if formset_error_title %}<h4 class="alert-heading">{{ formset_error_title }}</h4>{% endif %}
|
||||
<ul class="m-0">
|
||||
{{ formset.non_form_errors|unordered_list }}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% if field|is_checkbox %}
|
||||
<div class="form-group{% if 'form-horizontal' in form_class %} row{% endif %}">
|
||||
{% if label_class %}
|
||||
<div class="{% for offset in bootstrap_checkbox_offsets %}{{ offset }} {% endfor %}{{ field_class }}">
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<{% if tag %}{{ tag }}{% else %}div{% endif %} id="div_{{ field.auto_id }}" class="{% if not field|is_checkbox %}form-group{% if 'form-horizontal' in form_class %} row{% endif %}{% else %}{%if use_custom_control%}custom-control custom-checkbox{% else %}form-check{% endif %}{% endif %}{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
{% if field.label and not field|is_checkbox and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="{% if 'form-horizontal' in form_class %}col-form-label {% endif %}{{ label_class }}{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_checkboxselectmultiple %}
|
||||
{% include 'bootstrap4/layout/checkboxselectmultiple.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_radioselect %}
|
||||
{% include 'bootstrap4/layout/radioselect.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
|
||||
{% if field|is_checkbox and form_show_labels %}
|
||||
{%if use_custom_control%}
|
||||
{% crispy_field field 'class' 'custom-control-input' %}
|
||||
{% else %}
|
||||
{% crispy_field field 'class' 'form-check-input' %}
|
||||
{% endif %}
|
||||
<label for="{{ field.id_for_label }}" class="{%if use_custom_control%}custom-control-label{% else %}form-check-label{% endif %}{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% include 'bootstrap4/layout/help_text_and_errors.html' %}
|
||||
{% elif field|is_file and use_custom_control %}
|
||||
{% include 'bootstrap4/layout/field_file.html' %}
|
||||
{% else %}
|
||||
<div class="{{ field_class }}">
|
||||
{% crispy_field field %}
|
||||
{% include 'bootstrap4/layout/help_text_and_errors.html' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</{% if tag %}{{ tag }}{% else %}div{% endif %}>
|
||||
{% if field|is_checkbox %}
|
||||
{% if label_class %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,13 @@
|
||||
{% if inputs %}
|
||||
<div class="form-group{% if 'form-horizontal' in form_class %} row{% endif %}">
|
||||
{% if label_class %}
|
||||
<div class="aab {{ label_class }}"></div>
|
||||
{% endif %}
|
||||
|
||||
<div class="{{ field_class }}">
|
||||
{% for input in inputs %}
|
||||
{% include "bootstrap4/layout/baseinput.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,4 @@
|
||||
<div{% if alert.css_id %} id="{{ alert.css_id }}"{% endif %}{% if alert.css_class %} class="{{ alert.css_class }}"{% endif %}>
|
||||
{% if dismiss %}<button type="button" class="close" data-dismiss="alert">×</button>{% endif %}
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<input type="{{ input.input_type }}"
|
||||
name="{% if input.name|wordcount > 1 %}{{ input.name|slugify }}{% else %}{{ input.name }}{% endif %}"
|
||||
value="{{ input.value }}"
|
||||
{% if input.input_type != "hidden" %}
|
||||
class="{{ input.field_classes }}"
|
||||
id="{% if input.id %}{{ input.id }}{% else %}{{ input.input_type }}-id-{{ input.name|slugify }}{% endif %}"
|
||||
{% endif %}
|
||||
{{ input.flat_attrs|safe }}
|
||||
/>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user