from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin from django.utils import timezone from django.utils.translation import gettext_lazy as _ class CustomUserManager(BaseUserManager): """ 自定义用户模型的管理器。 """ def create_user(self, email, phone_number, password=None, **extra_fields): """ 创建并保存一个具有给定邮箱、手机号和密码的用户。 """ if not email: raise ValueError(_('用户必须有一个邮箱地址')) if not phone_number: raise ValueError(_('用户必须有一个手机号')) email = self.normalize_email(email) # 确保普通用户创建时这些字段为False或默认值 extra_fields.setdefault('is_staff', False) extra_fields.setdefault('is_superuser', False) extra_fields.setdefault('is_active', True) # 普通用户默认激活 user = self.model(email=email, phone_number=phone_number, **extra_fields) user.set_password(password) # 处理密码哈希 user.save(using=self._db) return user def create_superuser(self, email, phone_number, password=None, **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(_('超级用户必须将 is_staff 设置为 True.')) if extra_fields.get('is_superuser') is not True: raise ValueError(_('超级用户必须将 is_superuser 设置为 True.')) if not email: raise ValueError(_('超级用户必须有一个邮箱地址')) if not phone_number: raise ValueError(_('超级用户必须有一个手机号')) email = self.normalize_email(email) user = self.model(email=email, phone_number=phone_number, **extra_fields) user.set_password(password) user.save(using=self._db) return user class InterestTag(models.Model): # 将 InterestTag 定义在 CustomUser 之前,或者在 ManyToManyField 中使用字符串引用 name = models.CharField( _('标签名称'), max_length=50, unique=True, help_text=_('兴趣标签的名称,例如:摄影、篮球、Python编程') ) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('创建时间')) class Meta: verbose_name = _('兴趣标签') verbose_name_plural = _('兴趣标签们') ordering = ['name'] def __str__(self): return self.name class CustomUser(AbstractBaseUser, PermissionsMixin): email = models.EmailField(_('邮箱地址'), unique=True) phone_number = models.CharField(_('手机号'), max_length=20, unique=True) nickname = models.CharField(_('昵称'), max_length=100, blank=True) avatar = models.ImageField(_('头像'), upload_to='avatars/', null=True, blank=True) # 需要 Pillow 包 bio = models.TextField(_('简介'), blank=True) school = models.CharField(_('学校'), max_length=100, blank=True) is_staff = models.BooleanField( _('职员状态'), default=False, help_text=_('指明用户是否可以登录到管理站点。'), ) is_active = models.BooleanField( _('激活状态'), default=True, help_text=_( '指明用户是否被认为是活跃的。' '取消选择此项而不是删除账户。' ), ) date_joined = models.DateTimeField(_('注册日期'), default=timezone.now) # 用户的兴趣标签 (多对多关系) interests = models.ManyToManyField( 'InterestTag', # 使用字符串形式引用 InterestTag 模型 (或者将InterestTag定义在CustomUser之前) verbose_name=_('兴趣标签'), blank=True, # 允许用户没有任何兴趣标签 related_name='users_with_interest' # 明确的 related_name ) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['phone_number', 'nickname'] # 创建超级用户时需要的额外字段 objects = CustomUserManager() # 关联自定义的 Manager def __str__(self): return self.email @property # 作为一个属性来访问 def display_name(self): # 或者你喜欢的名字,比如 nickname_or_email return self.nickname if self.nickname else self.email class Meta: verbose_name = _('用户') verbose_name_plural = _('用户们')