Nuno_147
Nuno_147

Reputation: 2913

change a form value before validation in Django form

I have a django form and on my view function I do this :

search_packages_form = SearchPackagesForm( data = request.POST )

I would like to overwrite a form field called price which is decleared as such :

price = forms.ChoiceField( choices = PRICE_CHOICES, required = False,widget = forms.RadioSelect )

I would like to overwrite the form field before calling search_packages_form.is_valid()

I thought of doing :

search_packages_form.data['price'] = NEW_PRICE

But it does not work. Any ideas ?

Upvotes: 21

Views: 16539

Answers (4)

sipi09
sipi09

Reputation: 547

My solution is build on an earlier proposal. It is a working solution, which can be used in several cases.

@Milad Khodabandehloo had a tricky solution to solve the problem.

changed_data = dict(request.POST)
changed_data['price'] = NEW_PRICE
search_packages_form = SearchPackagesForm(data = changed_data)

as @The EasyLearn Academy commented: it does not allow you to access actual data submitted in form.

This is because the request.POST is immutable.

But there is a solution to the problem - just have to be more tricky.

This solution is only good if a reference to the object is enough for the certain cause. It leaves the object itself the same.

# write object to variable (data)
data = request.POST

# set to mutable
data._mutable = True

# modify the values in data 
data[modified_field] = new_value

# set mutable flag back (optional)
data._mutable = False

Hope it's useful!

Upvotes: 2

Milad Khodabandehloo
Milad Khodabandehloo

Reputation: 1977

one trick for what you want is to do it like this:

changed_data = dict(request.POST)
changed_data['price'] = NEW_PRICE
search_packages_form = SearchPackagesForm(data = changed_data)

Upvotes: 1

Ixio
Ixio

Reputation: 527

Probably not the Django way but based on https://stackoverflow.com/a/17304350/2730032 I'm guessing the easiest way to change your form value before validation is to do something like the following:

def search_packages_view(request):
    if request.method == 'POST'
        updated_request = request.POST.copy()
        updated_request.update({'price': NEW_PRICE})
        search_packages_form = SearchPackagesForm(updated_request)
        if search_packages_form.is_valid():
             # You're all good

This works but I'd be interested if anyone has another way that seems more in line with Django, or if there isn't: then an explanation about why.

Upvotes: 13

Hedde van der Heide
Hedde van der Heide

Reputation: 22449

form.is_valid() runs through your form's (and model's in case of a ModelForm) clean method's, returning True or False

If you plan on changing form data you can do it within the general clean method or at field level, e.g.

class YourForm(DerivingClass):
    # regular stuff

    def clean_<ATTR>(self):
        # here
        return self.cleaned_data

    def clean(self):
        # or here
        return super(YourForm, self).clean()

Upvotes: 1

Related Questions