Login

Reusable field forms using crispy-forms

Author:
axelwass
Posted:
August 25, 2015
Language:
Python
Version:
1.7
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

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 2 weeks ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 11 months ago
  5. Help text hyperlinks by sa2812 12 months ago

Comments

Please login first before commenting.