MBW
MBW

Reputation: 115

Passing data through Django forms

I feel I'm missing the obvious but I can't work it out!

I have written a custom form (for use outside of django admin), which I want to use to create / update instances of a number of model instances as well as hold conditional fields. However I seem to be losing my conditional data.

In my view I instansiate an instance of my form and pass it into the request context:-

view.py

form = MyForm(my_bool=True, pid=7)
render(request 'my_page.html', {'form': form})

forms.py

class MyForm(forms.Form):
    def __init__(self, *args, **kwargs):
        my_bool = kwargs.pop('my_bool', False)
        self.pid = kwargs.pop('pid', None)
        super(MyForm, self).__init__(*args, **kwargs)
        if my_bool:
            self.fields['textbox'] = forms.CharField(max_length=256)

That all works fine and the form renders as expected. Now when I submit the form it hits the below

view.py

 if request.method == 'POST':
        form = MyForm(request.POST)
        if form.is_valid():
        # Do Stuff

My problem is that the form object in the above code does not contain my 'textbox' or 'pid' fields even though the form I submitted did. I'm certain whatever I'm doing wrong is extremely obvious but from a whole lot of googling I cant work out a simple way to instantiate a form, pass it some data about what fields I want to show as well as say the id of the model I eventually want it to update and then have access to the info I passed in the post part of the code.

The # Do Stuff part of my code is supposed to take the 'pid' I passed to the form and use that to fetch a product e.g. Product.objects.get(pk=pid), however without storing the pid in the session I cant work out how to access it from the postback.

If a validation error occurs in my form i.e. form.is_valid() returns false I render the request again passing the form I already have, that way I see the validation errors however any conditional fields I passed initially are missing and their values ignored.

Maybe I'm just going about it completely wrong and I should be doing this a different way. What I am trying to achieve is a content entry form whose fields change depending on the type of product it is passed, once filled in the form saves the data to that instance of the product.

Any help would be greatly appreciated, I've found Django to be extremely accommodating to anything I've thrown at it so far and this feels like such a common use-case that I must just be doing it wrong!

I'm on Django v1.11 & Python v3.6.

Upvotes: 4

Views: 7773

Answers (1)

DisneylandSC
DisneylandSC

Reputation: 966

you are passing two arguments to create the form, namely my_bool and pid. But you are not passing those arguments in the POST view. In particular my_bool is None so the textbox field never gets generated. Changing

form = MyForm(request.POST)

to

form = MyForm(request.POST, my_bool=True, pid=7)

should do the trick.

Upvotes: 2

Related Questions