File: customization.rst

package info (click to toggle)
django-floppyforms 1.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,740 kB
  • ctags: 1,008
  • sloc: python: 4,477; makefile: 120
file content (110 lines) | stat: -rw-r--r-- 3,726 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
Customization
=============

Override default templates
--------------------------

Widgets have a ``template_name`` attribute that point to the template to use
when rendering the form. Default templates are provided, for instance the
default template for a ``TextInput`` and other input-type widgets is
``floppyforms/input.html``. You can easily override this template in your
project-level ``TEMPLATE_DIRS``, assuming they take precedence over app-level
templates.

Custom widgets with custom templates
------------------------------------

If you want to override the rendering behaviour only for a few widgets, you
can extend a ``Widget`` class from FloppyForms and override the
``template_name`` attribute::

    import floppyforms as forms

    class OtherEmailInput(forms.EmailInput):
        template_name = 'path/to/other_email.html'

Then, the output can be customized in ``other_email.html``:

.. code-block:: jinja

    <input type="email"
           name="{{ name }}"
           id="{{ attrs.id }}"
           placeholder="john@example.com"
           {% if value %}value="{{ value }}"{% endif %}>

Here we have a hardcoded placeholder without needing to instantiate the widget
with an ``attrs`` dictionary::

    class EmailForm(forms.Form):
        email = forms.EmailField(widget=OtherEmailInput())

.. _template_name_customization:

You can also customize the ``template_name`` without subclassing, by passing it
as an argument when instantiating the widget::

    class EmailForm(forms.Form):
        email = forms.EmailField(
            widget=forms.EmailInput(template_name='path/to/other_email.html'))

For advanced use, you can even customize the template used per-render, by
passing a ``template_name`` argument to the widget's ``render()`` method.

Adding more template variables
------------------------------

There is also a way to add extra context. This is done by subclassing the
widget class and extending the ``get_context()`` method::

    class OtherEmailInput(forms.EmailInput):
        template_name = 'path/to/other.html'

        def get_context(self, name, value, attrs):
            ctx = super(OtherEmailInput, self).get_context(name, value, attrs)
            ctx['foo'] = 'bar'
            return ctx

And then the ``other.html`` template can make use of the ``{{ foo }}`` context
variable.

``get_context()`` takes ``name``, ``value`` and ``attrs`` as arguments, except
for all ``Select`` widgets which take an additional ``choices`` argument.

In case you don't need the arguments passed to ``get_context()``, you can
extend ``get_context_data()`` which doesn't take any arguments::

    class EmailInput(forms.EmailInput):
        def get_context_data(self):
            ctx = super(EmailInput, self).get_context_data()
            ctx.update({
                'placeholder': 'hello@example.com',
            })
            return ctx

Altering the widget's ``attrs``
-------------------------------

All widget attibutes except for ``type``, ``name``, ``value`` and ``required``
are put in the ``attrs`` context variable, which you can extend in
``get_context()``:

.. code-block:: python

    def get_context(self, name, value, attrs):
        ctx = super(MyWidget, self).get_context(name, value, attrs)
        ctx['attrs']['class'] = 'mywidget'
        return ctx

This will render the widget with an additional ``class="mywidget"`` attribute.

If you want only the attribute's key to be rendered, set it to ``True``:

.. code-block:: python

    def get_context(self, name, value, attrs):
        ctx = super(MyWidget, self).get_context(name, value, attrs)
        ctx['attrs']['awesome'] = True
        return ctx

This will simply add ``awesome`` as a key-only attribute.