Login

Reusable field forms using crispy-forms

Author:
axelwass
Posted:
August 25, 2015
Language:
Python
Version:
1.7
Tags:
forms filters reuse reusable form-field crispy-forms
Score:
1 (after 1 ratings)

If you need to use some source to construct your form (maybe some database info or some user input), or you use the same fields with the same functionality in various forms and need to write the same piece of code for each of them, then you are looking in the right place. With this snippet you won't have those issues any more. :P

This snippet present a way to wean the fields from the form.

The code is made using crispy-forms, but the same idea can be applied without using it.

Best luck!

  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
# Auxiliar functions
def normalize(cadena):
    return ''.join([x for x in normalize('NFD', cadena) if category(x) != 'Mn'])

def to_normal_text(cadena):
    return normalize(cadena.lower().strip().replace(' ', '_').replace('/',  '_'))

# Snippet functions
def add_form_field(form_map, form_list, name, form_type, post, initial=None):
    if not initial:
        initial = {}
    initial.update({'label': name})
    form_id = to_normal_text(name)
    form = form_type(post, initial=initial, prefix=form_id)
    form_map[form_id] = form
    form_list.append(form)

def form_map_is_valid(form_map):
    valid = True
    for form in form_map:
        if form_map[form]:
            valid = valid and form_map[form].is_valid()
    return valid

# Snippet: form.py

class MainVariableForm(forms.Form):
    #add this form for the csrf in case the form would be a post
    def __init__(self, *args, **kwargs):
        super(FormCompuestoPrincipal, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False

class FieldForm(forms.Form):
    def get_filter(self):
        if self.cleaned_data['field']:
            return {'key': self.fields['field'].label, 'value': self.cleaned_data['field']}
        return None

    def __init__(self, *args, **kwargs):
        super(FieldForm, self).__init__(*args, **kwargs)
        self.fields['field'].label = kwargs.get('initial').get('label')
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.disable_csrf = True

# Examples: forms.py

class SpecificFieldForm1(FieldForm):
    field = forms.ChoiceField(choices=[('choice_1', '1'),
                                       ('choice_2', '2'))

    def get_filter(self):
        if self.cleaned_data['field']:
            return {'key': self.fields['field'].label,
                    'value': dict(self.fields['field'].choices)[self.cleaned_data['field']]}
        return None

class SpecificFieldForm2(FieldForm):
    field = forms.CharField(required=False)

# Example: view.py

def some_view(request):
    form_list = []
    form_map = {}
    add_form_field(form_map, form_list, 'Field 1 Label', SpecificFieldForm1, request.GET)
    add_form_field(form_map, form_list, 'Field 2 Label', SpecificFieldForm2, request.GET)
    add_form_field(form_map, form_list, 'Field 3 Label', SpecificFieldForm1, request.GET)

    filters= None
    if form_map_is_valid(form_map):
        # do stuff, use form_map['field_1_label'].cleaned_data['field'] for field reference.
        filters= [form.get_filter() for form in form_list]
    template = loader.get_template('some_template.html')
    context = RequestContext(request, {
        'forms': form_list,
        'filtros': filtros,
    })
    return HttpResponse(template.render(context))

# Example: some_template.html

<form method="get">
    {% csrf_token %}
    {% for form in forms %}
    {% if form %}
    {% crispy form %}
    {% endif %}
    {% endfor %}
    <div style="text-align: right">
        <input type="submit" name="submit" value="Filter" class="btn btn-primary" id="submit-id-submit">
    </div>
</form>
    <ul class="list-group">
        {% for filter in filtros %}
        {% if filter %}
        <li><strong>{{filter.key}}: </strong>{{filter.value}}</li>
        {% endif %}
        {% endfor %}
    </ul>
    # Show some data

More like this

Comments

Please login first before commenting.