django - 使用 django-allauth 注册多用户类型

标签 django django-forms django-allauth

编辑

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

Look at my own answer for a step-by-step guide (with explanation) of the right solution



TL;博士

如何使用 django-allauth 为私有(private)和公司用户实现注册?

我正在遵循的方法(正确吗?)

我有以下 models :
class PrivateUser(models.Model):
    """Models a private user account"""
    user = models.OneToOneField(User, on_delete=models.CASCADE)


class CompanyUser(models.Model):
    """Models the company's contact person user account"""
    user = models.OneToOneField(User, on_delete=models.CASCADE)


class Company(models.Model):
    """Models the company attributes"""
    contact_person = models.OneToOneField(User, related_name='company')
    name = models.CharField(max_length=50, null=False, blank=False)
    vat_no = models.CharField(
        # some config and validators
    )
    # ... other non-relevant fields

现在,我必须区分这两个用户 PrivateUserCompanyUser在 django-allauth 的注册过程中,只有一个 official django-allauth documentation 中指定的注册表单:

ACCOUNT_SIGNUP_FORM_CLASS (=None)

A string pointing to a custom form class (e.g. myapp.forms.SignupForm) that is used during signup to ask the user for additional input (e.g. newsletter signup, birth date). This class should implement a def signup(self, request, user) method, where user represents the newly signed up user.



因此,为了创建一个独特的表单,我创建了一个抽象模型类,其中包含所有
来自 PrivateUser 的字段和 CompanyUser加一(注意 user_type 字段):
class AbstractComprehensiveUser(models.Model):
    """
    Little hackish model class needed to handle one single sign up
    form for multiple users
    """

    USER_TYPE_CHOICES = (
        ('private', 'Private'),
        ('company', 'Company'),
    )

    user_type = models.CharField(
        max_length=10,
        blank=False,
        choices=USER_TYPE_CHOICES
    )

    # Common fields for either private and company users
    first_name = models.CharField(max_length=30, blank=False)
    last_name = models.CharField(max_length=30, blank=False)

    # Company specific fields
    company_name = models.CharField(max_length=50, null=True, blank=True)
    company_vat_no = models.CharField(
        # some config and validators
        null=True,
        blank = True
    )
    # other non-relevant fields

    class Meta:
        abstract = True

注:所有非公共(public)字段在此类中具有属性 null=Trueblank=True .

然后我创建了我的自定义 SignupForm如下:
class SignupForm(forms.ModelForm):
    first_name = forms.CharField(max_length=30)
    last_name = forms.CharField(max_length=30)

    class Meta:
        model = AbstractComprehensiveUser
        fields = (
            # Field to differentiate from private and company
            # user sign up
            'user_type',
            # Common fields for either private and company users
            'first_name', 'last_name',
            # Company specifc fields
            'company_name', 'company_vat_no', # etc etc
        )

现在的想法是使用具有两种形式的模板:
  • 隐藏的user_type='private'只是 first_namelast_name字段
  • 隐藏的user_type='company'以及来自 Company 的字段型号

  • 然后,在 SignupForm我将收到 user_type字段,我可以设置正确的形式,例如:
    class PrivateUserSignupForm(forms.ModelForm):
        first_name = forms.CharField(max_length=30)
        last_name = forms.CharField(max_length=30)
    
        class Meta:
            model = PrivateUser
            fields = ('first_name', 'last_name')
    

    问题是当我在 SignupForm.signup() 中检索数据时方法,User模型已经写入数据库。

    我不想保存它,而只是:
  • 验证
  • 接收 signup 中的数据填充正确表单的方法(PrivateUserSignupFormCompanyUserSignupForm)
  • 验证表格
  • 在没有错误的情况下保存用户和其他模型
  • 如果出现错误,请不要保存任何内容并警告用户有关错误

  • 问题是...
  • 这种方法正确吗?没有这些编译,还有其他方法可以实现这一点吗?
  • 如果这种方法是正确的,我该如何处理上面描述的工作流程?
  • 最佳答案

    我有同样的问题。我需要将 allauth 用于不同的用户配置文件类型。我扩展了 allauth SignupView 并将其用作在我的情况下,我有一个 MemberProfile 和 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,
      )
    

    我想要每种类型的个人资料都有一个单独的注册页面。幸运的是,allauth SignupView 将用户存储在 form_value() 方法中的实例上。我将 SignupView 扩展为 ProfileView ,它需要一个 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
    

    那么我的观点是这样的:
    #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
    

    关于django - 使用 django-allauth 注册多用户类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44505242/

    相关文章:

    django - 如何仅将子域关联到 Digital Ocean 上的 Django 应用程序?

    python - 判决是什么?在我的模型或模型表单中验证?

    javascript - $.get() 请求不适用于 Django

    python - Django All-Auth django.contrib.auth.backends.ModelBackend 语法无效

    django-templates - 如何覆盖 django allauth 电子邮件模板

    django - 如何将日期选择器与 django-filter 一起使用?

    python - 我如何在 django 中使用聚合

    javascript - 如何在Javascript中将字符串 "[7, 9]"转换为数组

    django - 在基于 Django 类的 View 中使用 modelformset_factory

    django - 如何在 django-allauth 上自定义 activate_url ?