0

I'm trying to create a page of my Django 1.5 project where users can change their presonal informations. I wrote a form:

class UserModify(forms.Form):
    middleschool = 'MS'
    highschool = 'HS'
    university = 'U'
    blank = ''
    male = 'M'
    female = 'F'
    mastercard = 'MC'
    maestro = 'M'
    visa = 'V'
    americanexpress = 'A'

    school_choices = ((middleschool, 'Middle School'), (highschool, 'High school'), (university, 'University'), (blank, 'Not Defined'),)
    sex = ((male, 'Male'), (female, 'Female'), (blank, 'Not defined'),)
    card_choices = ((mastercard, 'MasterCard'), (maestro, 'Mestro'), (visa, 'Visa/Visa Electron'), (americanexpress, 'American Express'),(blank, 'Not Defined'))

    password = forms.CharField(label = 'Password', widget=forms.PasswordInput)
    repassword = forms.CharField(label = ' Reinstert password', widget=forms.PasswordInput)
    name = forms.CharField(label = 'Name', required=False)
    surname = forms.CharField(label = 'Surname', required=False)
    school = forms.ChoiceField(choices = school_choices, required=False, label='What school are you enrolled?', initial = blank) 
    birthdate = forms.DateField(label = 'Birth date', required=False, widget=forms.extras.SelectDateWidget(years=range(1950, 2015)))
    sex = forms.ChoiceField(choices = sex, required=False, label='Sex', initial = blank)
    city = forms.CharField(label = 'City', required=False)
    paypal_info = forms.EmailField(required=False,)
    card_type = forms.ChoiceField(choices = card_choices, label='Card type', required=False)
    card_info = forms.CharField(min_length = 16, max_length = 16, label = 'Your card number', required=False,)
    def clean_repassword(self):
        repassword = self.cleaned_data['repassword']
        password = self.cleaned_data['password']
        if repassword != password:
            raise forms.ValidationError("Verification password different from original password!")
    widgets = {
            'password': forms.PasswordInput(),
            'birthdate': forms.extras.SelectDateWidget(years=range(1950, 2014))
    }

and this is the relative view:

def usermodify(request, user):
    mod_user = User.objects.get(username = user)
    if request.method == 'POST':
        form = UserModify(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            mod_user.password = cd['password']
            mod_user.first_name = cd['name']
            mod_user.last_name = cd['surname']
            mod_user.save()
            profile = mod_user.get_profile()
            profile.school = cd['school']
            profile.birthdate = cd['birthdate']
            profile.sex = cd['sex']
            profile.city = cd['city']
            profile.save()
            return render(request, 'user.html', {'request':request, 'view_user': mod_user, 'view_user_profile': profile})
    else:
        form = UserModify()
    return render(request, 'user_modify.html', {'form': form, 'request': request, 'modify_user': mod_user})

The form's rendering is as simple as it can get for now:

<form action="" method="post">
{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Modify">
    <input type="reset" value="Reset">
</form>

What I wantetd to do is populate the form by default with the current values in the object so that the User have to change only the one in which is interested and keep the others.

3 Answers 3

1

Use a ModelForm instead of a regular Form. A ModelForm can be associated with an instance, which is the used to prepopulate the form. If you want to update both the User and the profile, you can use two ModelForms in one view. For example:

class UserModelForm(forms.ModelForm):
    repassword = ... # additional fields that have no represenation in the model

    class Meta:
        model = User
        fields = ["username", "password", ]  # ...

    def clean(self):
        # ... your validation logic

class ProfileForm(forms.ModelForm):
    class Meta:
        model = YourProfileModel
        fields = []  # ...

Then use both in the view:

def usermodify(request, user):
    # mod_user = ...

    user_form = UserModelForm(request.POST or None, instance=mod_user)
    profile_form = ProfileForm(request.POST or None, instance=mod_user.get_profile())
    if user_form.is_valid() and profile_form.is_valid():
        user_form.save()  # this saves to the associated mod_user, as passed via the `instance` argument
        profile_form.save() 
        # ... redirect etc.
    return render(..., {'user_form': user_form, 'profile_form': profile_form})  # pass both forms to the template

In the template, put both forms inside of one <form> tag. Be sure that they don't have conflicting field names, or use a prefix.

Sign up to request clarification or add additional context in comments.

Comments

0
  1. If you are trying to get default values in the object. You can set that in your model, and these will carry over to your forms, and populate. Example:

    school_choices = models.CharField(blank=True, default='HS')

  2. Combine that with using Django's CBV's (Class Based Views) and the UdpdateView:

    https://docs.djangoproject.com/en/dev/ref/class-based-views/generic-editing/#updateview

The UpdateView will pre-populate your forms for you.

2 Comments

No, I already have a User object. I want the form which alows the user to change its personal infos to be populated by default by the current infos so that he can keep inalterated some fields and change only the ones in which he's interested.
ok, then you will just want to use the CBV UpdateView, and this will do that for you without you having to write a bunch of code for each form.
0

For future reference: I solved using Initial when rendering the form as showed here

1 Comment

Link is outdated

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.