35👍
Here is how I finally did :
class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(label=_(u'Prénom'), max_length=30)
last_name = forms.CharField(label=_(u'Nom'), max_length=30)
def __init__(self, *args, **kw):
super(UserProfileForm, self).__init__(*args, **kw)
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
self.fields.keyOrder = [
'first_name',
'last_name',
...some_other...
]
def save(self, *args, **kw):
super(UserProfileForm, self).save(*args, **kw)
self.instance.user.first_name = self.cleaned_data.get('first_name')
self.instance.user.last_name = self.cleaned_data.get('last_name')
self.instance.user.save()
class Meta:
model = UserProfile
41👍
I stumbled across this today and after some googling I found a solution that is a bit cleaner in my opinion:
#in forms.py
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ["username", "email"]
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
#in views.py
def add_user(request):
...
if request.method == "POST":
uform = UserForm(data = request.POST)
pform = UserProfileForm(data = request.POST)
if uform.is_valid() and pform.is_valid():
user = uform.save()
profile = pform.save(commit = False)
profile.user = user
profile.save()
....
...
#in template
<form method="post">
{{ uform.as_p }}
{{ pform.as_p }}
<input type="submit" ...>
</form>
- [Django]-Django : Unable to import model from another App
- [Django]-Django : Serving static files through nginx
- [Django]-GeoDjango GEOSException error
5👍
This is how I did it in the current trunk (Revision: 11804). The solution of Natim was not working for me.
In admin.py
:
class ProfileAdmin(admin.ModelAdmin):
form = ProfileForm
def save_model(self, request, obj, form, change):
obj.user.first_name = form.cleaned_data['first_name']
obj.user.last_name = form.cleaned_data['last_name']
obj.user.save()
obj.save()
In forms.py
:
class ProfileForm(forms.ModelForm):
first_name = forms.CharField(max_length=256)
last_name = forms.CharField(max_length=256)
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
try:
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
except User.DoesNotExist:
pass
class Meta:
fields = ['first_name', 'last_name', ...etc.]
- [Django]-Django: SocialApp matching query does not exist
- [Django]-Passing variable from django template to view
- [Django]-Django suffix ForeignKey field with _id
1👍
You can also try to use the django-basic-apps project which has a profiles app:
- [Django]-How to query Case-insensitive data in Django ORM?
- [Django]-How to pass a variable from settings.py to a view?
- [Django]-Django datetime issues (default=datetime.now())
1👍
This is something i used in one my projects long back hopefully it should help out the others googling this problem .
class SignUpForm(forms.ModelForm):
first_name = forms.CharField(max_length = 30)
last_name = forms.CharField(max_length = 30)
username = forms.CharField(max_length = 30)
password = forms.CharField(widget = forms.PasswordInput)
password1 = forms.CharField(widget = forms.PasswordInput)
class Meta:
model = UserProfile
exclude = ['user']
def clean_username(self): # check if username does not exist before
try:
User.objects.get(username=self.cleaned_data['username']) #get user from user model
except User.DoesNotExist :
return self.cleaned_data['username']
raise forms.ValidationError("This user exist already choose an0ther username")
def clean(self, *args , **kwargs):
super(SignUpForm).clean(*args ,**kwargs) # check if password 1 and password2 match each other
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:#check if both pass first validation
if self.cleaned_data['password1'] != self.cleaned_data['password2']: # check if they match each other
raise forms.ValidationError("Passwords don't match each other")
return self.cleaned_data
def save(self): # create new user
new_user = User.objects.create_user(username=self.cleaned_data['username'],password=self.cleaned_data['password1'],email=self.cleaned_data['email'])
new_user.first_name = self.cleaned_data['first_name']
new_user.last_name = self.cleaned_data['last_name']
new_user.save()
UserProf = super(SignUpForm,self).save(commit = False)
UserProf.user = new_user
UserProf.save()
return UserProf
- [Django]-Django comparing model instances for equality
- [Django]-Order Django Query Results by Foreign Key
- [Django]-Django REST Framework viewset per-action permissions
0👍
I take it normal that you don’t find any information in the docs as you merge two models into a single form.
Alternatively and maybe very obviously you can: Create two modelforms, one for the user and the other for the userprofile. Set the userprofile modelform to display only firstname and lastname. Put both forms in the same template within a single <form>
tag. When it is submitted, call the save methods of each form.
- [Django]-DEBUG = True Django
- [Django]-Get django object id based on model attribute
- [Django]-Rendering JSON objects using a Django template after an Ajax call
0👍
Why not have two model forms on the back-end and just present them as a single form in your template? Drop the name fields from your UserProfileForm and create a second model form for the user object?
- [Django]-Best practice for storing auth tokens in VueJS?
- [Django]-In django, how do I call the subcommand 'syncdb' from the initialization script?
- [Django]-Django Imagefield not working properly via ModelForm