cola
cola

Reputation: 12466

How can I change a Django form field value before saving?

if request.method == 'POST':
    userf = UsersModelForm(request.POST)
    username = userf.data['username']
    password = userf.data['password']
    passwordrepeat = userf.data['passwordrepeat']
    email = userf.data['email']

I tried this:

    tempSalt = bcrypt.gensalt()
    password = bcrypt.hashpw(password,tempSalt)
    passwordrepeat = bcrypt.hashpw(passwordrepeat,tempSalt)

    userf.data['password'] = password
    userf.data['passwordrepeat'] = passwordrepeat

But i got error. How can i change the value of userf.data['password'] and userf.data['passwordrepeat'] before saving?

Error:

AttributeError at /register

This QueryDict instance is immutable

Request Method:     POST
Request URL:    http://127.0.0.1:8000/register
Django Version:     1.3.1
Exception Type:     AttributeError
Exception Value:    

This QueryDict instance is immutable

Exception Location:     /usr/local/lib/python2.6/dist-packages/django/http/__init__.py in _assert_mutable, line 359
Python Executable:  /usr/bin/python
Python Version:     2.6.6
Python Path:    

['/home/user1/djangoblog',
 '/usr/lib/python2.6',
 '/usr/lib/python2.6/plat-linux2',
 '/usr/lib/python2.6/lib-tk',
 '/usr/lib/python2.6/lib-old',
 '/usr/lib/python2.6/lib-dynload',
 '/usr/local/lib/python2.6/dist-packages',
 '/usr/lib/python2.6/dist-packages',
 '/usr/lib/python2.6/dist-packages/gst-0.10',
 '/usr/lib/pymodules/python2.6',
 '/usr/lib/pymodules/python2.6/gtk-2.0']

Upvotes: 44

Views: 77581

Answers (6)

Jesus Rodriguez
Jesus Rodriguez

Reputation: 12018

If you need to do something to the data before saving, just create a function like this in your ModelForm class:

def clean_nameofdata(self):
    data = self.cleaned_data['nameofdata']
    # do some stuff
    return data

All you need is to create a function with the name clean_nameofdata where nameofdata is the name of the field, so if you want to modify password field, you need:

def clean_password(self):

if you need to modify passwordrepeat

def clean_passwordrepeat(self):

So inside there, just encrypt your password and return the encrypted one.

I mean:

def clean_password(self):
    data = self.cleaned_data['password']
    # encrypt stuff
    return data

so when you valid the form, the password would be encrypted.

Upvotes: 62

henrykohl
henrykohl

Reputation: 36

The original question is "to modify/update a form field value before saving". Some methods above seem to be used after saving. This reference may be useful in solving This QueryDict instance is immutable. You may try the following method

if request.method == 'POST':
    userf = UsersModelForm(request.POST)
    ...
    data = request.POST.copy()
    # remember old state
    _mutable = data._mutable

    # set to mutable
    data._mutable = True

    data['password'] = password
    data['passwordrepeat'] = passwordrepeat

    # set mutable flag back
    data._mutable = _mutable

    userf = UsersModelForm(data)

    if userf.is_valid():
        userf.save()

Upvotes: 0

Özer
Özer

Reputation: 2106

In Views:

def post(self, request, *args, **kwargs):
    form = self.form_class(request.POST)
    if form.is_valid():
        obj = form.save(commit=False)
        obj.my_field = 'value'
        obj.save()

In Forms:

instance = form.instance
instance.user = request.user
instance.save()

But be careful, this does not check is_valid(). If you want to do that, you can instantiate the form with the new values:

# NOT TESTED, NOT SURE IF THIS WORKS...
form = MyForm(instance=instance)
if form.is_valid():
    form.save()

Upvotes: 3

Bite code
Bite code

Reputation: 596753

Override _clean methods and put your checks in them. You can modify cleaned_data from there.

E.g:

def clean_password(self):
    new1 = self.cleaned_data['password']
    return new1

Every fields in the form will have a field_name_clean() method created automatically by Django. This method is called when you do form.is_valid().

Upvotes: 7

Serafim Suhenky
Serafim Suhenky

Reputation: 2160

You will have problems if you need to fill form from POST, change any form field value and render form again. Here is solution for it:

class StudentSignUpForm(forms.Form):
  step = forms.IntegerField()

  def set_step(self, step):
    data = self.data.copy()
    data['step'] = step
    self.data = data

And then:

form = StudentSignUpForm(request.POST)
if form.is_valid() and something():
  form.set_step(2)
  return  render_to_string('form.html', {'form': form})

Upvotes: 10

Burhan Khalid
Burhan Khalid

Reputation: 174624

See the documentation for the save() method

if request.method == 'POST':
    userf = UsersModelForm(request.POST)
    new_user = userf.save(commit=False)

    username = userf.cleaned_data['username']
    password = userf.cleaned_data['password']
    passwordrepeat = userf.cleaned_data['passwordrepeat']
    email = userf.cleaned_data['email']

    new_user.password = new1
    new_user.passwordrepeat = new2

    new_user.save()

Upvotes: 23

Related Questions