Multiple user type sign up with django-allauth

前端 未结 2 1065
没有蜡笔的小新
没有蜡笔的小新 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!

提交回复
热议问题