Cleaning TypedChoiceFields - data doesn't go to cleaned_data

Hello guys!

I have some little problem. I have three classes of fields in my form. The problem happens in case of TypedChoiceField. I receive raw data, but after standard cleaning this data doesn’t goes to cleaned_data, just disapears… I don’t have any idea how to check what’s going on. Have anyone idea for that?

views.py

class QueryBuilderView(FormView):
    template_name = 'query_builder/query_builder.html'
    form_class = QueryBuilderForm
    success_url = '/'

    def get_form(self, form_class=None):
        settings_ids = self.request.session.get('temp_data')
        if form_class is None:
            self.form_class = self.get_form_class()
        return self.form_class(settings_ids, **self.get_form_kwargs())

forms.py

def __init__(self, settings_ids, *args, **kwargs):
        super(QueryBuilderForm, self).__init__(*args, **kwargs)

        settings = all_settings.filter(id__in=settings_ids)

        for s in settings:
            name = f'setting_{s.id}'
            values = s.settingvalue_set.all()
            if values.exists():
                choices = values.values_list('id', 'human_readable')
                coerce_list = values.values_list('human_readable')
                self.fields[name] = forms.TypedChoiceField(
                    label=s.descriptor, choices=choices, coerce=coerce_list, required=False)
            else:
                self.fields[name] = forms.CharField(
                    label=s.descriptor, required=False)

            self.fields[name].group = s.group

Can we see the complete view?

Of course Ser! But there is nothing special more.

class QueryBuilderView(FormView):
    template_name = 'query_builder/query_builder.html'
    form_class = QueryBuilderForm
    success_url = '/'

    def get_form(self, form_class=None):
        settings_ids = self.request.session.get('temp_data')
        if form_class is None:
            self.form_class = self.get_form_class()
        return self.form_class(settings_ids, **self.get_form_kwargs())

    def form_valid(self, form):
        data = form.cleaned_data
        print(data)
        return super().form_valid(form)

But originally I’m calling for cleaned_data in clean() function in form.

class QueryBuilderForm(forms.Form):

    query = forms.CharField(required=True)

    def __init__(self, settings_ids, *args, **kwargs):
        super(QueryBuilderForm, self).__init__(*args, **kwargs)

        settings = all_settings.filter(id__in=settings_ids)

        for s in settings:
            name = f'setting_{s.id}'
            values = s.settingvalue_set.all()
            if values.exists():
                choices = list(values.values_list('id', 'human_readable'))
                coerce_list = list(values.values_list('human_readable'))
                self.fields[name] = forms.TypedChoiceField(
                    label=s.descriptor, choices=choices, coerce=coerce_list, required=False)
            else:
                self.fields[name] = forms.CharField(
                    label=s.descriptor, required=False)

            self.fields[name].group = s.group

    def clean(self):
        data = self.data
        cleaned_data = super().clean()
        print(data)
        print(cleaned_data)
        return cleaned_data

Ok, and to confirm, you’re saying that in your form’s clean method, print(data) has all the data submitted from the form and print(cleaned_data) is showing everything except the dynamically created choice fields. Am I understanding the situation correctly?

I’m getting the impression that there’s also more to this form than what you’ve posted here. Is there any other validation-related methods to this form that you haven’t shown? (You might also want to review the Form and Field validation page for information on what methods are called and the sequence in which they are called.)

I don’t have any specific information at this point, but there are a couple more things you can try to track this down. If you’re not comfortable with using a debugger to monitor your code and trace its execution, there are more things you can print to try and gather more information.

Since self.cleaned_data is created by the is_valid method before clean gets called, you should also be able to print(self.cleaned_data) in your clean method before you call super. You could also print(self.as_p()) to see what the status of the form is at that point.

You might also want to check for errors at this point as well, to see if any have been registered in the form - print(self.errors) or print(self.errors.as_data())