Skip to content
Snippets Groups Projects
Commit ae233971 authored by Tim Fechner's avatar Tim Fechner
Browse files

Add basic formhandling

still no 'per field' error handling, but coming soon!
parent 1ad02664
No related branches found
No related tags found
No related merge requests found
......@@ -3,16 +3,17 @@
This django-app provides everything you ever wanted! (probably not, but i hope you feel happy anyways). It brings fonts,
styles, javascript and layouts as templates.
Please read the [wiki](https://lab.it.hs-hannover.de/django/hshassets/wikis/home) for further information about the
provided templates.
Please read the [wiki](https://lab.it.hs-hannover.de/django/hshassets/wikis/templates) for further information about the
available templates.
## Shipped awesome stuff
## Packed with awesome stuff
The current version of this package ships the following own stuff and awesome third-party libraries
### Own stuff
- CD Content like Images under `static/hshassets/img/hsh_brand`
- [Bulma styled forms](https://lab.it.hs-hannover.de/django/hshassets/wikis/bulma-styled-forms), feels like CrispyForms
### Third party libraries
......
from django.utils.safestring import mark_safe
from django.utils.html import format_html
from hshassets.forms.utils import render_form_field
class AbstractElement(object):
markup = ''
def __init__(self, *args, **kwargs):
self.elements = args
def render(self, content):
return format_html(self.markup, content)
class Field(AbstractElement):
def __init__(self, field_name, *args, **kwargs):
super().__init__(*args, **kwargs)
self.field_name = field_name
def render(self, field):
return mark_safe(render_form_field(field))
class Columns(AbstractElement):
markup = '<div class="columns is-multiline">{}</div>'
class Column(AbstractElement):
markup = '<div class="column is-{}">{}</div>'
def __init__(self, width, *args, **kwargs):
super().__init__(*args, **kwargs)
self.width = width
def render(self, content):
return format_html(self.markup, self.width, content)
class Card(AbstractElement):
markup = '<div class="card">{}<div class="card-content">{}</div></div>'
card_header_markup = '<header class="card-header"><p class="card-header-title">{}</p></header>'
def __init__(self, *args, title='', **kwargs):
super().__init__(*args, **kwargs)
self.title = title
def render(self, content):
if self.title:
return format_html(self.markup, format_html(self.card_header_markup, self.title), content)
else:
return format_html(self.markup, self.title, content)
class Submit(AbstractElement):
markup = '<div class="field"><div class="control"><button type="submit" class="button {}">{}</button></div></div>'
def __init__(self, label, css_class='', *args, **kwargs):
super().__init__(*args, **kwargs)
self.label = label
self.css_class = css_class
def render(self, content):
return format_html(self.markup, self.css_class, self.label)
from django.utils.safestring import mark_safe
from django.utils.html import format_html
def render_form_field(field):
wrapper = BulmaFieldMarkup()
try:
out = getattr(wrapper, field.field.widget.input_type)(field, field.as_widget())
except AttributeError:
out = wrapper.label(field.label, wrapper.div_control(field.as_widget()))
return wrapper.div_field(field, out)
class BulmaFieldMarkup(object):
"""
HTML wrapper for input fields to add bulma styles.
"""
def div_field(self, field, content):
"""Bulma requires to wrap every input field with this <div class="field">"""
return format_html('<div class="field">{}</div>', content)
def div_control(self, content):
"""Bulma requires to wrap input elements with an <div class="control">"""
return format_html('<div class="control">{}</div>', content)
def label(self, label, content='', css_class='label', for_id=''):
"""Define <label> seperately so it can be used elsewhere instead as a children of the <div class="field">"""
return format_html('<label for="{}" class="{}">{}</label> {}', for_id, css_class, label, content)
def select(self, field, content):
"""Dropdowns have an extra wrapping <div class="select">"""
return self.label(field.label, self.div_control(format_html('<div class="select">{}</div>', content)))
def checkbox(self, field, content):
"""Checkboxes are super special, they wrap the input field with the label"""
return self.div_control(self.label(mark_safe(content + ' ' + field.label), css_class='checkbox'))
def radio(self, field, content):
choice_markup = ''
for choice in field:
choice_markup += self.label(
choice.tag(), choice.choice_label.title(),
for_id=choice.id_for_label, css_class='radio'
)
return self.div_control(mark_safe(choice_markup))
from django import template
from django.utils.safestring import mark_safe
from hshassets.forms.utils import render_form_field
from hshassets.forms.elements import Field
register = template.Library()
@register.simple_tag
def bulmaform(form):
"""Templatetag to render forms with bulma styles and elements"""
# because the <input> tag will be rendered by django's internals, it is easier to give the widgets
# a css-class rather than render every <input> tag by mysqlf
for field in form:
# not every form element in bulma has the 'input' css class, so we need to differ here
if getattr(field.field.widget, 'input_type', None) not in ['checkbox', 'radio']:
field.field.widget.attrs = {'class': 'input' + (' is-danger' if field.errors else '')}
if getattr(form, 'layout', None):
output = render_layout(form.layout, form)
else:
output = render_without_layout(form)
return mark_safe(output)
def render_layout(elements, form):
element_html = ''
for element in elements:
if isinstance(element, Field):
# if the element itself is an field, give it the form field instance and render it
element_html += element.render([field for field in form if field.name == element.field_name][0])
else:
content = ''
# if the element has some child elements, render them
if getattr(element, 'elements', []):
content += render_layout(element.elements, form)
# and now put the rendered things into the element's html markup
element_html += element.render(mark_safe(content))
return mark_safe(element_html)
def render_without_layout(form):
output = ''
for field in form:
output += render_form_field(field)
return mark_safe(output)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment