Search code examples
djangodjango-formsdjango-custom-field

Handling Multiple User Inputs in Custom Django Form Field: Processing All Values


I am working on creating a custom form field in Django where users can input multiple text values dynamically at the frontend. However, I'm facing an issue where only the last text input value is being processed in the to_python method of the field, even though I can see all the input values in the Request.POST.

multiple text values custom field

Here is a simplified version of my code:

#fields.py
class MultiCharField(forms.Field):
    widget = Mywidget

    def __init__(self, *args, **kwargs):
        super(MultiCharField, self).__init__(*args, **kwargs)     
    
    def to_python(self, value):
        print("value: " + str(value)) # it only prints the last text input
        return value if isinstance(value, list) else [value]
<!-- mywidget.html -->
<div class="choice">
        <input type="text" class="form-control" id="id-{{ widget.name }}" name="{{ widget.name }}"
        {% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %} />
        <a href="#" class="add-field">Add Another</a>
</div>
<script>
    $( ".add-field" ).on( "click", function() {
        $('<div class="choice"><input type="text" name="{{ widget.name }}" /><a href="#" class="remove-field">Remove</a></div>').insertAfter($(this).parent());
        $('.remove-field').on('click', function() {
            $(this).parent().remove();
    });
    });
</script>
#forms.py
class QuestionModelForm(forms.ModelForm):
    options = MultiCharField()

    class Meta:
        model = Question
class Mywidget(forms.Widget):
    template_name = 'mywidget.html'

    def get_context(self, name, value, attrs=None):
        return {'widget': {
            'name': name,
            'value': value,
        }}

    def render(self, name, value, attrs=None, renderer=None):
        context = self.get_context(name, value, attrs)
        template = loader.get_template(self.template_name).render(context)
        return mark_safe(template)

I aim to capture all the text inputs entered by the user in my custom field rather than just the last one. The Request.POST shows all the values correctly, but I'm struggling to handle them properly within my custom field's to_python method. How can I process all the text inputs entered by the user in my custom field?


Solution

  • I successfully resolved the problem by referring to the Django documentation, which states that the value_from_datadict method is responsible for returning the widget's value. Therefore, I found it necessary to override this method in my custom widget.

    def value_from_datadict(self, data, files, name):
        return data.getlist(name, None)