Reputation: 235
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.
Upvotes: 0
Views: 1397
Reputation: 235
For future reference: I solved using Initial
when rendering the form as showed here
Upvotes: 0
Reputation: 6735
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 ModelForm
s 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
.
Upvotes: 1
Reputation: 20780
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')
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.
Upvotes: 0