0

I'm trying to do something that should be very simple: adding a field to signup and saving it to my user object. I am using allauth, so the way this is supposed to be done as far as I can tell is by modifying the allauth form for signup. I've followed the instructions here: How to customize user profile when using django-allauth:

This is what my forms.py looks like:

from allauth.account.forms import SignupForm
from django import forms

UNASSIGNED = 'NA'
CLIENT = 'CL'
USER_TYPE_CHOICES = (
    (UNASSIGNED, 'Unassigned'),
    (CLIENT, 'Client'),
)

class CustomSignupForm(SignupForm):
    user_type = forms.CharField( 
        widget=forms.Select(choices=USER_TYPE_CHOICES))
    def signup(self, request, user):
        user.user_type = self.cleaned_data['user_type']
        user.save
        return user

and then my custom user:

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=254, unique=True)
    name = models.CharField(max_length=254, null=True, blank=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    
    UNASSIGNED = 'NA'
    CLIENT = 'CL'
    USER_TYPE_CHOICES = (
        (UNASSIGNED, 'Unassigned'),
        (CLIENT, 'Client'),
    )
    user_type = models.CharField(max_length=2,
                                      choices=USER_TYPE_CHOICES,
                                      default=UNASSIGNED)

    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def get_absolute_url(self):
        return "/users/%i/" % (self.pk)

I know that the field that I added to the user works as I can see it in the admin and access it in the shell. The form renders properly (I can see the drop down for the new field.) The problem is that the form never saves the new user_type field, it always shows up as unassigned. I would greatly appreciate any advice on troubleshooting! I've been working on this a while and I haven't found any threads with the same issue.

John
  • 75
  • 11

2 Answers2

1

ok, after trying many different posted solutions, I found something that works. I'm not exactly sure why, so I would love an explanation if anyone has it, but I'm posting this here in case someone else comes along with a similiar problem and just wants the solution.

This is what my end signupform form looked like:

class CustomSignupForm(SignupForm):
    user_type = forms.CharField( 
        widget=forms.Select(choices=USER_TYPE_CHOICES))

    class Meta:
        model = User

    def save(self, request):
        user = super(CustomSignupForm, self).save(request)
        user.user_type = self.cleaned_data['user_type']
        user.save()
        return user

instead of including a signup() function it looks like you need to use def save(self, request): as signup is (I think) deprecated. Then you need to add user = super(MyCustomSignupForm, self).save(request) as is mentioned in the docs here. That's the part I really don't understand but there it is. I'll try to remember to come back and edit this if I figure it out.

John
  • 75
  • 11
0

I did have the same challenge when I was starting using Allauth. The main difference is that Allauth uses the DefaultAccountAdapter to handle the save_user logic. This is where super comes in. As mentioned in this SO post you call the Parent's save function together with your own save function when using super. When not calling super here the custom fields never get passed into the adapter. Try discovering the DefaultaccountAdapter by writing your own custom one:

custom_adapter.py

class CustomAccountAdapter(DefaultAccountAdapter): 
     # your custom logic 
     return user #or whatever your user model is called 

And don't forget to put it into your settings:

ACCOUNT_ADAPTER = 'yourappname.custom_adapter.CustomAccountAdapter'

Happy coding!

Rick
  • 211
  • 4
  • 11