Paulo
Paulo

Reputation: 7362

django custom field and widget

Im writing a custom field/widget to display multiple input fields for related data, for example my product has 4 search fields, search1, search2, search3, etc.. , instead of having to define each field in my form, i want to have one field that will display as many input fields as i need ( all related data ) based on its length, here's what i have so far

class RelatedCategoryField(forms.MultiValueField):
    """
    Custom field to display multiple input boxes for a related object
    """

    def __init__(self, max_length, sub_max_length, label):
        # sub_max_length, is the max_length of each subfield
        self.total =  max_length/sub_max_length
        self.widget = CategoryWidget(self.total, label)
        fields = ()
        for num in range(self.total):
            fields += (forms.CharField(label="%s-%s" %(label, num),
                            max_length=sub_max_length),)
        super(RelatedCategoryField, self).__init__(fields, required=False)

    def compress(self, value_list):
        if value_list:
            return value_list
        return [[] for i in self.total]

class CategoryWidget(forms.MultiWidget):
    """
    Custom widget
    """
    def __init__(self, count, label):
        self.count = count
        self.label = label
        widgets = [forms.TextInput(attrs={}) for sub in range(self.count)]
        super(CategoryWidget, self).__init__(widgets)

    def decompress(self, value):
        if value:
            return value
        return [None for i in range(self.count)]

    def format_output(self, rendered_widgets):
        """
        Customize widget rendering
        """
        return render_to_string('fields/categoryfield.html', {'fields': rendered_widgets})

so basically i call this field like so:

category = RelatedCategoryField(max_length=200, sub_max_length50, label="search")

then based on sub_max_length the field determines how many fields it will create for this multivalue field and then the field label will be label+field# ( search_1, search_2, etc.. )

the above code is working fine, but my problem is that when displayed, the field only shows the label provided when the field was defined, and then it shows the input fields, i want to show each input field with its corresponding label, so to summarize my question, is it possible to display the label per field inside the multivalue field ?

Upvotes: 0

Views: 2448

Answers (2)

FSp
FSp

Reputation: 1645

i did something similar in my application defining the format_output as follows:

    def format_output(self, rendered_widgets):
        return mark_safe(u'<p class="placewidget">%s %s %s<br />%s %s %s %s %s %s</p>' % (
            _('Name:'), rendered_widgets[1],rendered_widgets[0],
            _('ZIP:'), rendered_widgets[2],
            _('City:'), rendered_widgets[3],
            _('State:'), rendered_widgets[4],
    ))

this renders each widget separately and with its label. hope it helps

Upvotes: 2

zallarak
zallarak

Reputation: 5525

I don't know if this is what you're looking for, as it involves editing the template instead of the form.

In your template, you could do something like this:

# In form_snippet.html:

{% for field in form %}
    <div class="fieldWrapper">
    {{ field.label_tag }}: {{ field }}
    </div>
{% endfor %}

Source: https://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

Upvotes: 1

Related Questions