本文介绍了Python-在Django 2中创建多种用户类型并将电子邮件作为用户名字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Python(3.7)和Django(2.2)开发一个项目,在该项目中我必须实现多种类型的用户:


  1. 个人帐户-18岁以下

  2. 个人帐户-18岁以上

  3. 父母帐户

  4. 教练帐户

  5. 管理员

此外,我还需要使用使用电子邮件作为用户名字段进行登录/身份验证。



我的策略是m尝试使用的方法是从 AbstractBaseUser 继承的 User 建立自定义基本模型,并创建一个自定义的用户管理器电子邮件设置为用户名,但它不起作用。 / p>

这是我完整的模型代码:

  class UserManager(BaseUserManager): 

def _create_user(自身,电子邮件,密码,is_staff,is_superuser,** extra_fields):
(如果未发送电子邮件):
提高ValueError('用户必须保持ave a email address')
now = timezone.now()
email = self.normalize_email(email)
user = self.model(
email = email,
is_staff = is_staff,
is_active = True,
is_superuser = is_superuser,
last_login = now,
date_joined = now,
** extra_fields

user.set_password(password)
user.save(using = self._db)
返回用户

def create_user(self,email = None,password = None, ** extra_fields):
返回self._create_user(电子邮件,密码,False,False,** extra_fields)

def create_superuser(自我,电子邮件,密码,** extra_fields):
用户= self._create_user(电子邮件,密码,True,True,** extra_fields)
user.save(using = self._db)
返回用户


def generate_cid():
customer_number = .join([i中的[random.choice(string.digits) range(10)])
return customer_number


类User(AbstractBaseUser,PermissionsMixin):
email = models.EmailField(max_length = 255,unique = True)
is_personal_above_18 =模型.BooleanField(默认= False)
is_personal_below_18 =模型.BooleanField(默认= False)
is_parent =模型.BooleanField(默认= False)
is_staff =模型。 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)

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

对象= UserManager()

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

def get_email (self):
return self.email


class PersonalAccountAbove18( models.Model):
user = models.OneToOneField(User,on_delete = models.CASCADE,
primary_key = True,related_name ='profile')
customer_id = models.BigIntegerField(default = generate_cid )


类PersonalAccountBelow18(models.Model):
user = models.OneToOneField(User,on_delete = models.CASCADE,
primary_key = True,related_name =' profile')
customer_id = models.BigIntegerField(blank = False)


class ParentAccount(models.Model):
user = models.OneToOneField(User,on_delete = models.CASCADE,
primary_key = True,related_name ='profile')
customer_id = models.BigIntegerField(default = generate_cid)

我对自己的方法感到困惑,甚至当我运行 makemigrations 时也返回错误:


解决方案

makemigrations 及更高版本中的错误(在删除 PermissionsMixin )要求使用用户名而不是电子邮件进行身份验证,这表明您尚未将自定义模型设置为 default 用户模型,供Django auth 应用程序使用。结果,Django使用 auth.User 模型作为默认用户模型,并且您的模型像其他模型一样被添加到项目中。因此,两个用户模型同时存在,其中 auth.User 是用于身份验证目的的默认/活动模型。



本质上,编辑 settings.py 以添加以下内容:

  AUTH_USER_MODEL ='<您的应用程序> ;.用户'

现在Django将使用您自定义的 User 模型,而不是 auth 应用(默认)和 auth.User 模型将被删除。 auth 应用程序使用 get_user_model django.contrib.auth.get_user_model )函数获取项目的当前活动用户模型,该模型检查 settings.AUTH_USER_MODEL ,默认情况下检查系统的其余部分(例如 admin 应用程序)还检查此设置以获取当前用户模型。因此,只要您使用 auth 应用程序,上面的内容就足够了。


I'm working on a project using Python(3.7) and Django(2.2) in which I have to implement multiple types of users as:

  1. Personal Account - below 18
  2. Personal Account - above 18
  3. Parent Account
  4. Coach Account
  5. Admin

along with that, I also need to use email as the username field for login/authentication.

The strategy I'm trying to use is to build a custom base model as User inherited from AbstractBaseUser and also created a custom User Manager to make the email as username but it's not working.

Here's my complete model code:

class UserManager(BaseUserManager):

    def _create_user(self, email, password, is_staff, is_superuser, **extra_fields):
        if not email:
            raise ValueError('Users must have an email address')
        now = timezone.now()
        email = self.normalize_email(email)
        user = self.model(
            email=email,
            is_staff=is_staff,
            is_active=True,
            is_superuser=is_superuser,
            last_login=now,
            date_joined=now,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email=None, password=None, **extra_fields):
        return self._create_user(email, password, False, False, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        user = self._create_user(email, password, True, True, **extra_fields)
        user.save(using=self._db)
        return user


def generate_cid():
    customer_number = "".join([random.choice(string.digits) for i in range(10)])
    return customer_number


class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=255, unique=True)
    is_personal_above_18 = models.BooleanField(default=False)
    is_personal_below_18 = models.BooleanField(default=False)
    is_parent = models.BooleanField(default=False)
    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)

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

    objects = UserManager()

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

    def get_email(self):
        return self.email


class PersonalAccountAbove18(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE,
                                primary_key=True, related_name='profile')
    customer_id = models.BigIntegerField(default=generate_cid)


class PersonalAccountBelow18(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE,
                                primary_key=True, related_name='profile')
    customer_id = models.BigIntegerField(blank=False)


class ParentAccount(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE,
                                primary_key=True, related_name='profile')
    customer_id = models.BigIntegerField(default=generate_cid)

I'm confused about my approach and even it's also return an error when I run makemigrations as:

解决方案

The errors in makemigrations, and later (after dropping PermissionsMixin) requiring username instead of email for authentication are hints that you have not set your custom model as the default user model to be used by the Django auth app. As a result, Django is using the auth.User model as the default user model and your one being added to the project like any other model. So both of the user models exist simultaneously with the auth.User being the default/active one used for authentication purposes.

In essence, edit your settings.py to add the following:

AUTH_USER_MODEL = '<your_app>.User'

Now Django will use your customized User model instead of the one from auth app (the default) and the auth.User model will be dropped. The auth app uses the get_user_model (django.contrib.auth.get_user_model) function to get the currently active user model for the project which checks for settings.AUTH_USER_MODEL, and by default the rest of the system (e.g. the admin app) also checks for this setting to get the current user model. So as long as you're using the auth app the above should suffice.

这篇关于Python-在Django 2中创建多种用户类型并将电子邮件作为用户名字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-27 08:25