javascriptdjangoformslistmultiplechoicefield

Django: Form with list of integers


I have a javascript application (in angular) that calls my django application. It uses lists of integers to filter the response. In Django I'm using a form to clean the data.

Javascript:

app.factory('SearchData', 
      function(){
            return {
                shop:[],
                sort:'',
                xhr:'',
                brand:[],
             };
       });
app.factory('SearchQuery',
        ['$http', '$location', '$route', 'SearchData', 
        function($http, $location, $route, SearchData){
            return {
                getItems: function(){
                    return $http.get('/search/',{
                        params: SearchData,
                        responseType: 'json',
                    });
                }
            };
        }
    ]);

Python form:

class SearchForm(forms.Form):
    shop = forms.IntegerField(widget=forms.SelectMultiple(),required=False)
    sort = forms.CharField(max_length=1, min_length=1, required=False)
    brand = forms.IntegerField(widget=forms.SelectMultiple(),required=False)

I get a list of integers in shop and brand but I do not how to handle it on the django side. I don't want to use MultipleChoiceField as I need to supply choices in form (which creates an unnecessary query). All I want to do is have a list of integers.

The form above throws "Enter a whole number.". I could just ditch the form and use request.GET.getlist('shop') (which works). But I'd rather use a form if possible...

Update, for now I'm using a MultipleChoiceField and pass the choices before validation in the view. Like:

shops = request.GET.getlist('shop', None)
sf = SearchForm(request.GET)
sf.fields['shop'].choices = shops

It works, but it isn't pretty.


Solution

  • Use a custom widget/field:

    from django import forms
    from django.core.exceptions import ValidationError
    
    
    class MultipleValueWidget(forms.TextInput):
        def value_from_datadict(self, data, files, name):
            return data.getlist(name)
    
    
    class MultipleValueField(forms.Field):
        widget = MultipleValueWidget
    
    
    def clean_int(x):
        try:
            return int(x)
        except ValueError:
            raise ValidationError("Cannot convert to integer: {}".format(repr(x)))
    
    
    class MultipleIntField(MultipleValueField):
        def clean(self, value):
            return [clean_int(x) for x in value]
    
    
    class SearchForm(forms.Form):
        shop = MultipleIntField()