Adrien Kaczmarek
Adrien Kaczmarek

Reputation: 550

(Django) How to clean an unbound form?

I have a problem. I looked at the web for a solution but did not find one. If my problem already have an answer, please give me the links.


The Problem

Here is the problem:

I create a form inside one of my view with some initial values:

form = MyForm(initial=initial)

However, I do not have a full control over these initial values, thus I need to check is the form is valid. However, because the form in unbound .is_valid() always return False.


So, I tried to create an bound form from the first step:

form = MyForm(initial)

However, I do not initialize all the field, simply because I do not know their name and how many they are, thus I cannot initialize all of them.
The problem is that some of the field I do not initialize are required. Thus, the .is_valid() always return False because I do not provide required field(s).
What I know is that all of the required field have a default value.


When I created the form with initial values (i.e. MyForm(initial=initial)), the defaults value are provided. So I wish I could do something like:

form = MyForm(initial=initial)
form = MyForm(form)

However, that obviously doesn't work.


I see two potential solution to my problem:

  1. Validate an unbound form
  2. Get a list with all the fields and their default values (if one) (I do not know this list in advance)


I do not know how to make 2, however, I tried this for 1:

form = MyForm(initial=initial)
form.clean()

form.clean() calls a custom function where I stated (I had no problem with a bound form):

cleaned_date = super().clean()

That returns the following errors:

AttributeError at XXX

'MyForm' object has no attribute 'cleaned_data'


And well, that is kind of logical, the form is unbound, thus the data are not cleaned yet.


Any piece of advice (or complete solution) will be greatly appreciated.
Thank you for having reading me.


Wrong Solution (that works, but too wordly/ugly)

There is one solution to this problem but I am sure this is not the could one (it is way too ugly).

I first create a unbound field:

form = MyForm()

Then I read the initial value of the fields inside the string representation of the form.

for field in form:
    index_name = str(field.find("name"
    name = field[index_name+len('name="':]
    name = name[:name.find('"')]

    index = str(field).find("value")
    if index >= 0: # if their is a default value
        value = field[index+len('value="'):]
        value = value[:value.find('"')]
        
        initial[name] = value

Then I just need to remake the form, bound this time:

form = MyForm(initial)

However, this solution is overwhelming and I am sure there is a better way to go.


Upvotes: 0

Views: 226

Answers (2)

stefanw
stefanw

Reputation: 10570

Ideally you would get the default values and do an initial.update(defaults) and hand it to the form.

If the defaults are not available to you, you can try to remove fields from the form that are not in initial.

form = MyForm(data=initial)
field_keys = list(form.fields.keys())
for field_name in field_keys:
    if field_name not in initial:
        form.fields.pop(field_name)
form.is_valid()  # <- only validates fields in initial

Upvotes: 2

林敬智
林敬智

Reputation: 113

Maybe you can initialize your form with your initial values with no full control, and run form.is_valid() and use the form.cleaned_data to initial another form? But Why would you have to do validating on the unbound form? I think this scenario is rare.

Upvotes: 0

Related Questions