Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django-创建两种用户类型,其中一种类型可以同时是两种类型_Python_Django_Django Allauth_Cookiecutter Django - Fatal编程技术网

Python Django-创建两种用户类型,其中一种类型可以同时是两种类型

Python Django-创建两种用户类型,其中一种类型可以同时是两种类型,python,django,django-allauth,cookiecutter-django,Python,Django,Django Allauth,Cookiecutter Django,我们需要为两种不同类型的用户提供两个单独的表单。称他们为Client和Provider。客户端将是父级、基本用户,而提供者是一种扩展。在任何时候,客户机也可以成为提供者,同时仍然保持客户机的状态和信息。因此,提供者既有作为客户端的权限,也有作为提供者的权限 我是Django的新手。我们要做的就是注册任何一种用户类型,但是如果用户直接注册为提供者,那么提供者和客户机表之间就有一对一的关系 我们认为,我们遇到的问题是适配器。提供者可以注册,但最终会出现在users\u user表中,在生成的user

我们需要为两种不同类型的用户提供两个单独的表单。称他们为
Client
Provider
。客户端将是父级、基本用户,而提供者是一种扩展。在任何时候,客户机也可以成为提供者,同时仍然保持客户机的状态和信息。因此,提供者既有作为客户端的权限,也有作为提供者的权限

我是Django的新手。我们要做的就是注册任何一种用户类型,但是如果用户直接注册为提供者,那么提供者和客户机表之间就有一对一的关系

我们认为,我们遇到的问题是适配器。提供者可以注册,但最终会出现在
users\u user
表中,在生成的
users\u provider
表中没有条目。这是我们试图在数据库中保存和关联这两个实体的方式,还是其他方式

我们正试图利用allauth进行身份验证和注册

我们的守则:

models.py:

class User(AbstractUser):
    name = models.CharField(_('Name of User'), blank=True, max_length=255)
    def __str__(self):
        return self.username

    def get_absolute_url(self):
        return reverse('users:detail', kwargs={'username': self.username})

    SEX = (
        ("M","MALE"),
        ("F","FEMALE"),
    )

    birthdate = models.DateField(_('Birth Date'), default=django.utils.timezone.now, blank=False)
    sex = models.CharField(_('Sex'), choices=SEX, max_length=1, default="M")
    isProvider = models.BooleanField(_('Provider'), default=False)


#Using User, not models.Model
class Provider(User):

    HAS_BUSINESS = (
        ('YES','YES'),
        ('NO','NO'),
    )

#Resolving asociation 1:1 to User 
#NOTE: AUTH_USER_MODEL = users.User in setting
    owner = models.OneToOneField(settings.AUTH_USER_MODEL)
    has_business = models.CharField(_('Do you have your own business?'),max_length=2, choices=HAS_BUSINESS, default='NO')
    isProvider = True
我们的表格.py

class ProviderForm(SignupForm,ModelForm):

    name = forms.CharField(label='Name', strip=True, max_length=50)
    lastname = forms.CharField(label='Last Name', strip=True, max_length=50)
    Provider.isProvider = True

    class Meta:
        model = Provider
        fields = '__all__'
        exclude = GENERAL_EXCLUSIONS + [
        'owner',
        ]

class ClientForm(SignupForm,ModelForm):

    name = forms.CharField(label='Name', strip=True, max_length=50)
    lastname = forms.CharField(label='Last Name', strip=True, max_length=50)

    class Meta:
        model = User
        fields = "__all__"
        exclude = GENERAL_EXCLUSIONS

    def is_active(self):
        return False

    def __init__(self, *args, **kwargs):
        super(ClientForm, self).__init__(*args, **kwargs)
views.py:

class ProviderRegisterView(SignupView):
    template_name = 'account/form_provider.html'
    form_class = ProviderForm
    redirect_field_name = 'next'
    view_name = 'registerprovider'
    success_url = None

    def get_context_data(self, **kwargs):
        ret = super(ProviderRegisterView, self).get_context_data(**kwargs)
        ret.update(self.kwargs)
        return ret

registerprovider = ProviderRegisterView.as_view()


#View para el formulario de registro de usuarios clientes
class ClientRegisterView(SignupView):

    template_name = 'account/form_client.html'
    form_class = ClientForm
    redirect_field_name = 'next'
    view_name = 'registerclient'
    success_url = None

    def get_context_data(self, **kwargs):
        ret = super(ClienteRegisterView, self).get_context_data(**kwargs)
        ret.update(self.kwargs)
        return ret

registerclient = ClienteRegisterView.as_view()
最后,我们的adapter.py:

#Per allauth documentation, settings changed:
#ACCOUNT_ADAPTER = 'projectname.users.adapters.RegisterUserAdapter'

class RegisterUserAdapter(DefaultAccountAdapter):
    def save_user(self, request, user, form, commit=True):
        data = form.cleaned_data
        user.first_name = data['name']
        user.last_name = data['lastname']
        #Saving Client info
        user.sex = data['sex']
        user.birthdate = data['birthdate']
        #Normal allauth saves
        user.username = data['username']
        user.email = data['email']
        if user.isProvider:
            p = Provider()
            p.owner = user
            p.has_business = data['has_business']
        if 'password1' in data:
            user.set_password(data['password1'])
        else:
            user.set_unusable_password()
        self.populate_username(request, user)
        if commit:
            #Save user
            user.save()
            #If it's also a Provider, save the Provider 
            if user.isProvider:
                p.save()
        return user

任何帮助或提示都将不胜感激。如果我遗漏了什么,请告诉我。我不确定问题是否出在模型本身、表示表单的方式或适配器上。就其现状而言,无论我们使用何种形式,它始终保存为基本用户表(我们的客户机),提供者表从不将信息保存到其中。

对于Django的新自定义用户模型,只能将一个用户模型设置为
设置。AUTH\u User\u model
。在您的示例中,您可以将其设置为
用户
模型

class User(AbstractUser):
    ...
    provider = models.OneToOneField(Provider, null=True)

class Provider(models.Model):
    ...
然后,对于可选的提供者数据,创建一个单独的模型,该模型由
OneToOneField
用户
模型中引用

class User(AbstractUser):
    ...
    provider = models.OneToOneField(Provider, null=True)

class Provider(models.Model):
    ...
考虑到
AUTH\u user\u模型
约束,这是在Django中处理多个用户类型的最简单方法

另外,最好只对抽象模型进行子类化,否则会得到多任务继承,这会导致隐藏的隐含连接,从而降低性能

最后,您可以在自定义表单的
表单中创建
提供程序
对象。is\u valid()
方法并分配
user.Provider=Provider