pythondjangoformsdjango-forms

Django, get value of the ChoiceField form


I have a form which contain a choicefield of items on my database. My question is How can I get the selected value of my choicheField?

forms.py

class list_data(forms.Form):
    message = forms.CharField(widget=forms.Textarea)

    def __init__(self, author, *args, **kwargs):
        super(list_data, self).__init__(*args, **kwargs)
        self.fields['List'] = forms.ChoiceField(
            choices=[(o.id, str(o)) for o in List.objects.filter(author=author)]
        )

views.py

def sms(request):
    form2  = list_data(author=request.user)

    if request.method == "POST":
        form2 = list_data(request.POST)
        if form2.is_valid():
            choice = form2.cleaned_data["List"]
            print(choice)

    else:
        return render(request, "data_list/sms.html", {"form2": form2})


    return render(request, "data_list/sms.html", {"form2": form2})

When I try to press the submit button it give me this error:

 int() argument must be a string, a bytes-like object or a number, not 'QueryDict'

So I changed the form2 = list_data(request.POST) for form2 = list_data(author=request.user) the error is gone but it print nothing else.

Thanks for helping

models.py

class List(models.Model):
    item = models.CharField(max_length=100)
    content = models.TextField()
    site = models.CharField(max_length=11, choices=THE_SITE)
    content_list = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)


    def __str__(self):
        return self.item

Solution

  • In case of a POST request, you pass request.POST as first parameter, and thus as author, and not as data. You can rewrite the view to:

    def sms(request):
        if request.method == 'POST':
            form2 = list_data(request.user, data=request.POST)
            if form2.is_valid():
                choice = form2.cleaned_data["List"]
                print(choice)
        else:
            form2  = list_data(author=request.user)
        return render(request, "data_list/sms.html", {"form2": form2})

    I would however advise to use a ModelChoiceField [Django-doc] here that will remove some boilerplate logic, and then you can work with model objects:

    class ListDataForm(forms.Form):
        message = forms.CharField(widget=forms.Textarea)
        list = forms.ModelChoiceField(queryset=List.objects.none())
    
        def __init__(self, author, *args, **kwargs):
            super(list_data, self).__init__(*args, **kwargs)
            self.fields['list'].queryset = List.objects.filter(author=author)

    Note that according to the PEP-0008 style guidelines, the classes should be written in PerlCase (so ListDataForm, not list_data), and the attributes should be written in snake_case, so list, not List.