Multiple user type sign up with django-allauth

前端 未结 2 1059
没有蜡笔的小新
没有蜡笔的小新 2020-12-04 23:11

EDIT

Please, do not waste your time reading the question... it is the wrong approach!

Look at my own answer for a step-by-step g

相关标签:
2条回答
  • 2020-12-04 23:34

    TL;DR

    All the messy stuff I wrote above are junk!

    The (final) right solution

    In settings.py remove ACCOUNT_SIGNUP_FORM_CLASS, we won't use it.

    Suppose to have the following models:

    class PrivateUser(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
    
    class CompanyUser(models.Model):
        contact_person = models.OneToOneField(User, on_delete=models.CASCADE)
        company_name = models.CharField(max_length=50, null=False, blank=False)
    

    Now, what we want is to let our app signup the PrivateUser and the CompanyUser with different forms.

    To accomplish that we'll extends the django-allauth's SignupForm and SignupView.

    In forms.py:

    from myapp.models import CompanyUser
    
    class CompanySignupForm(SignupForm):
        # declare here all the extra fields in CompanyUser model WITHOUT
        # the OneToOneField to User
        # (N.B: do NOT try to declare Meta class with model=CompanyUser,
        # it won't work!)
        company_name = forms.CharField(max_length=50, required=True, strip=True)
    
        # Override the save method to save the extra fields
        # (otherwise the form will save the User instance only)
        def save(self, request):
            # Save the User instance and get a reference to it
            user = super(CompanySignupForm, self).save(request)
            # Create an instance of your model with the extra fields
            # then save it.
            # (N.B: the are already cleaned, but if you want to do some
            # extra cleaning just override the clean method as usual)
            company_user = CompanyUser(
                contact_person=user,
                company_name=self.cleaned_data.get('company_name')
            )
            company_user.save()
    
            # Remember to return the User instance (not your custom user,
            # the Django one), otherwise you will get an error when the
            # complete_signup method will try to look at it.
            return company_user.contact_person
    

    Now, we have CompanyUser model and CompanySignupForm form. Let's create a CompanyUserSignupView view in views.py with the following code:

    class CompanyUserSignupView(SignupView):
        # The referenced HTML content can be copied from the signup.html
        # in the django-allauth template folder
        template_name = 'account/signup_company.html'
        # the previously created form class
        form_class = CompanySignupForm
    
        # the view is created just a few lines below
        # N.B: use the same name or it will blow up
        view_name = 'company_signup'
    
        # I don't use them, but you could override them
        # (N.B: the following values are the default)
        # success_url = None
        # redirect_field_name = 'next'
    
    # Create the view (we will reference to it in the url patterns)
    company_signup = CompanyUserRegistrationView.as_view()
    

    Last step, the urls.py:

    urlpatterns = [
        # ...
        url(
            r'^accounts/signup/company/$',
            views.company_signup,
            name='signup-company'
        ),
    ]
    

    Now, just use your browser to go to http://localhost:8000/accounts/signup/company (or the proper url pattern based on your configuration).

    You will find the extra fields and you can signup a company user.

    Now repeat all the previous steps to create a PrivateSignupForm form, a PrivateUserSignupView view and add the proper url pattern to let users signup as privates.

    LAST WARNING

    The django-allauth default signup url will still works unless you override it with one of your url... and you should do that!

    0 讨论(0)
  • 2020-12-04 23:37

    I had the same problem. I needed to use allauth for different user profile types. I extended the allauth SignupView and used it as a In my case I have a MemberProfile and PartnerProfile:

    #profile models
    
    class MemberProfile(models.Model):
      user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
      )
    
    
    class PartnerProfile(models.Model):
      user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
      )
    

    I want a separate signup page for each type of profile. Luckily the allauth SignupView stores the user on it's instance in the form_value() method. I extend the SignupView as ProfileView which expects a profile_class :

    #mixin
    
    from allauth.account.views import SignupView
    from allauth.account.forms import SignupForm
    
    
    class ProfileSignupView(SignupView):
    
      template_name = 'profiles/register.html'
      success_url = ''  # profile specific success url
      form_class = SignupForm
      profile_class = None  # profile class goes here
    
      def form_valid(self, form):
        response = super(ProfileSignupView, self).form_valid(form)
        profile = self.profile_class(user=self.user)
        profile.save()
    
        return response
    

    then my views look like this:

    #views
    
    from .mixins import ProfileSignupView
    from .models import PartnerProfile, MemberProfile
    
    class MemberSignupView(ProfileSignupView):
    
       success_url = '/member/profile'
       profile_class = MemberProfile
    
    
    class PartnerSignupView(ProfileSignupView):
    
        success_url = '/partner/profile'
        profile_class = PartnerProfile
    
    0 讨论(0)
提交回复
热议问题