4

I extended standard user model with UserProfile model, with following fields:

class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='profile')
    gender = models.CharField(max_length=30)
    info = models.CharField(max_length=30)

but while creating a new user using this form:

class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='First name')
    last_name = forms.CharField(max_length=30, label='Last name')
    info = forms.CharField(max_length=30, label='info')
    def save(self, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        profile = UserProfile()
        profile.user = user     
        profile.info = self.cleaned_data['info']
        profile.save()
        user.profile = profile
        user.save()

the 'info' is always empty ('') in the database (as is any other field except id). Standard attributes (first, last name) are saved correctly.

I tried debugging and the error is not related to SQL, as the query is not right:

INSERT INTO "user_profile" ("user_id", "info") VALUES (17, '',
 '') RETURNING "user_profile"."id";

But, when I debug the value of user.profile.info using pdb it works correctly:

(Pdb) user.profile.info
u'info passed from form'
George
  • 497
  • 5
  • 15
  • Do you have `ACCOUNT_SIGNUP_FORM_CLASS = 'your_app.forms.SignupForm'` in your settings? – illagrenan Jan 24 '14 at 20:25
  • Yes I do, sorry forgot to mention that – George Jan 24 '14 at 21:14
  • I tried your code and `self.cleaned_data['info']` contains data that I have eventered into the form (so I think that your problem is not related to django-allauth). Maybe you can try something like `profile.info = u"some_test_data"`. – illagrenan Jan 24 '14 at 22:07
  • Yes that part returns data correctly. I started fiddling with the code and I started getting 'can't set attribute' error on 'user.profile = profile' line, so I removed it and now it works. I tried this solution http://stackoverflow.com/a/17635831/1856554, but it didn't work for me. I'm not adding my solution as accepted answer, as I'm not sure if it is correct. – George Jan 24 '14 at 23:29
  • Can you try to replace `def save(self, user)` with `def signup(self, request, user)`? – andrea.ge Oct 10 '14 at 08:13
  • Have a look at this question, answered by Django allauth author: http://stackoverflow.com/q/12303478/247696 – Flimm Mar 09 '17 at 12:36

2 Answers2

2

The custom form should be saved first but with commit set to false so the information dosen't hit the database yet, after that the user fields can be saved and then you can set your one-to-one field linking the two tables before you finally save

class SignupForm(forms.Form):    
    def signup(self, user):
        profile = UserProfile()
        profile.save(commit = False)
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.save()
        user.profile = profile
        profile.user = user     
        profile.info = self.cleaned_data['info']
        profile.save()

by the way we're setting profile.user not user.profile profile is the child inheriting from the parent (User class) in this case

Flimm
  • 136,138
  • 45
  • 251
  • 267
danidee
  • 9,298
  • 2
  • 35
  • 55
-1

You are overwriting the wrong method in order to save the user information. The method to override is signup and not save:

class SignupForm(forms.Form):
    ..........

    def signup(self, request, user):

        .....................
Sudip Kafle
  • 4,286
  • 5
  • 36
  • 49
  • The save method does exist though signup also exist and it is not clear when should one override which method. Some more details on the answer would definitely help and I would want to vote up this answer then. – Divick Mar 23 '15 at 09:26
  • I see that in the latest version of allauth, signup is the way to intercept the user creation but it seems to be called after the user has already been persisted to DB. One needs to override save_user method of a custom AccountAdapter to be able to intercept the user creation form before the user has been persisted to DB. – Divick Mar 23 '15 at 12:03