How to format Django form with UIKit styling

Viewed 459

I am struggling to see a way to style a django form in the style of a uikit horizontal form. UIKit has the styling I want and Django has the validation and templating I want.A way to implement a datepicker too would be useful.

I have tried the plain django form template with .as_p and .as_table. I have also tried to use Meta and widgets but couldn't get that to work. I can't see how I can add the needed uikit tags to each element and add the uk-form-controls div.

template.html

<form class="uk-form-horizontal uk-margin-large uk-align-center">
    <div class="uk-margin">
        <label class="uk-form-label" for="form-horizontal-text">Job Title</label>
        <div class="uk-form-controls">
            <input class="uk-input uk-form-width-large" id="form-horizontal-text" type="text" placeholder="Some text...">
        </div>
    </div>

forms.py

class job_form(forms.Form):
    job_title = forms.CharField(label='Job Title', max_length=50)
    hiring_manager = forms.CharField(label='Hiring Manager', max_length=50)
    job_description = forms.CharField(label='Job Description', max_length=50)
    salary = forms.IntegerField()
    closing_date = forms.DateField()

I am expecting to be able to have the uikit form styling with the templating and validation of django forms but am yet to get it to work.

1 Answers

Django has a variety of ways to override the form behavior and layout. I see you are using forms.Form instance. Simply add your classes to the form class like:

class NiceForm(forms.Form):
    solid_field=forms.CharField(widget=forms.TextInput(attrs={'class': 'uk-form-input'}))

Although it is simple, but sluggish, when you want introduce breaking changes to the layout, I would override the template (or render method if you like) to bundle a reusable widget. Simple example to extract the form to external reusable template as you can render them manually as HTML like documentation.

Leave the form clean and use templatetag to override classes:

# _form_icludes.html

{% for field in form.visible_fields %}
    <fieldset class="uk-fieldset">
        <div class="uk-margin">
            <label class="uk-form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>

              <div class="uk-form-controls">

                {% if field.field.widget.input_type  == 'select' %}
                {{ field | add_css_cls:'uk-select'}}
                {% elif field.field.widget.input_type  == 'option'%}
                {{ field | add_css_cls:'uk-option'}}
                {% elif field.field.widget.input_type  == 'checkbox'%}
                {{ field | add_css_cls:'uk-checkbox'}}
                {% elif field.field.widget.input_type  == 'select'%}
                {{ field | add_css_cls:'uk-select'}}
                {% elif field.field.widget.input_type  == 'file'%}
                {{ field }}

                {% else %}
                {{ field | add_css_cls:'uk-input'}}

                {% endif %}

                {% if field.help_text %}
                    <span class="uk-text-small uk-text-left uk-text-italic">
                     {{ field.help_text }}
                    </span>
                {% endif %}
                {% if field.errors %}
                        {% for error in field.errors %}
                    <p class="uk-flex uk-flex-middle uk-text-danger ">
                        <span data-uk-icon="icon:warning" class="uk-text-danger uk-margin-small-right"></span>
                        {{ error | escape }}
                    <p/>

                </div>
                    {% endfor %}
                {% endif %}

         </div>
   </fieldset>

{% endfor %}

# add_css_cls

from django import template

register = template.Library()

@register.filter
def add_css_cls(value, arg):
    css_classes = value.field.widget.attrs.get('class', '').split(' ')
    if css_classes and arg not in css_classes:
        css_classes = '%s %s' % (css_classes, arg)
    return value.as_widget(attrs={'class': css_classes})

There are many different ways.

Related