所以我以前使用过django-allauth,它非常适合用户注册和登录功能。
我目前正在开发一个需要某种“来宾退房”功能的小型应用程序,员工应该能够创建用户而无需注册(创建密码或登录可能性)
我可以使用用户模型中使用的相同信息为来宾帐户创建一个单独的模型,这是最简单的解决方案,但违反了干燥原则。
由于我继承了“ AbstractBaseUser”以使用电子邮件字段作为唯一标识符来创建一个用户帐户,因此我认为我们可以将模型拆分为“ CustomAccount”模型,需要一个电子邮件地址并设置一个单独的模型来存储所有用户信息并设置guest_flag。
我们现在可以使用guest_user创建订单,但是之后我们无法注册来宾的电子邮件地址或将其转换为注册用户。
另一方面,我们无法两次创建“来宾定单”,因为我们使用电子邮件地址作为唯一标识符,或者我们不应该为来宾定单注册电子邮件地址,但是之后我们就无法通知他们订单更新。
有人对使用来宾帐户和注册用户有指导,建议吗?
下面是我尝试用于将用户模型分为帐户和用户模型的代码。
'''
Functionality
#1;
- A user can signup using their emailaddress and password to create an account.
- Before a user can create an order, their emailaddress needs to be verified.
- Once the emailaddress has been verified, the user can create an order himself (or herself).
#2;
- A user flagged as "is_employee" can create an guest user without the need for an emailaddress or password.
- An employee can than use the newly created guest user to create an order.
'''
# "CustomAccount" model, overriding the default "User" model
class CustomAccount(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True, null=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
USERNAME_FIELD = 'email'
objects = CustomAccountManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
# OneToOne model adding personal information to the account
class CustomUser(models.Model):
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
street = models.CharField(max_length=200, blank=True)
street_number = models.CharField(max_length=4, blank=True, null=True)
postcode = models.CharField(max_length=7, blank=True, null=True)
city = models.CharField(max_length=200, blank=True)
remark = models.TextField(max_length=1000, blank=True)
# Set primary_ket to True
user = models.OneToOneField('CustomAccount', on_delete=models.CASCADE, primary_key=True, blank=True, null=True)
# Flags
is_guest = models.BooleanField(default=False)
is_employee = models.BooleanField(default=False)
# When a new user is created from the admin area and CustomUser data has not been updated, link CustomUser to emailaddress
def __str__(self):
return (self.last_name, self.first_name)
# When an account is created, create new record for CustomUser as well.
@receiver(post_save, sender=CustomAccount)
def create_custom_user(sender, instance, created, **kwargs):
if created
CustomUser.objects.create(user=instance)
@receiver(post_save, sender=CustomAccount)
def save_custom_user(sender, instance, **kwargs):
instance.customuser.save()
class CustomAccountManager(BaseUserManager):
"""
A custom user manager to deal with emails as unique identifiers for auth
instead of usernames. The default that's used is "UserManager"
"""
def _create_user(self, email, password, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('The Email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)