models.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. from django.db import models
  2. from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
  3. from django.utils import timezone
  4. from django.utils.translation import gettext_lazy as _
  5. class CustomUserManager(BaseUserManager):
  6. """
  7. 自定义用户模型的管理器。
  8. """
  9. def create_user(self, email, phone_number, password=None, **extra_fields):
  10. """
  11. 创建并保存一个具有给定邮箱、手机号和密码的用户。
  12. """
  13. if not email:
  14. raise ValueError(_('用户必须有一个邮箱地址'))
  15. if not phone_number:
  16. raise ValueError(_('用户必须有一个手机号'))
  17. email = self.normalize_email(email)
  18. # 确保普通用户创建时这些字段为False或默认值
  19. extra_fields.setdefault('is_staff', False)
  20. extra_fields.setdefault('is_superuser', False)
  21. extra_fields.setdefault('is_active', True) # 普通用户默认激活
  22. user = self.model(email=email, phone_number=phone_number, **extra_fields)
  23. user.set_password(password) # 处理密码哈希
  24. user.save(using=self._db)
  25. return user
  26. def create_superuser(self, email, phone_number, password=None, **extra_fields):
  27. """
  28. 创建并保存一个具有给定邮箱、手机号和密码的超级用户。
  29. """
  30. extra_fields.setdefault('is_staff', True)
  31. extra_fields.setdefault('is_superuser', True)
  32. extra_fields.setdefault('is_active', True)
  33. if extra_fields.get('is_staff') is not True:
  34. raise ValueError(_('超级用户必须将 is_staff 设置为 True.'))
  35. if extra_fields.get('is_superuser') is not True:
  36. raise ValueError(_('超级用户必须将 is_superuser 设置为 True.'))
  37. if not email:
  38. raise ValueError(_('超级用户必须有一个邮箱地址'))
  39. if not phone_number:
  40. raise ValueError(_('超级用户必须有一个手机号'))
  41. email = self.normalize_email(email)
  42. user = self.model(email=email, phone_number=phone_number, **extra_fields)
  43. user.set_password(password)
  44. user.save(using=self._db)
  45. return user
  46. class InterestTag(models.Model): # 将 InterestTag 定义在 CustomUser 之前,或者在 ManyToManyField 中使用字符串引用
  47. name = models.CharField(
  48. _('标签名称'),
  49. max_length=50,
  50. unique=True,
  51. help_text=_('兴趣标签的名称,例如:摄影、篮球、Python编程')
  52. )
  53. created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('创建时间'))
  54. class Meta:
  55. verbose_name = _('兴趣标签')
  56. verbose_name_plural = _('兴趣标签们')
  57. ordering = ['name']
  58. def __str__(self):
  59. return self.name
  60. class CustomUser(AbstractBaseUser, PermissionsMixin):
  61. email = models.EmailField(_('邮箱地址'), unique=True)
  62. phone_number = models.CharField(_('手机号'), max_length=20, unique=True)
  63. nickname = models.CharField(_('昵称'), max_length=100, blank=True)
  64. avatar = models.ImageField(_('头像'), upload_to='avatars/', null=True, blank=True) # 需要 Pillow 包
  65. bio = models.TextField(_('简介'), blank=True)
  66. school = models.CharField(_('学校'), max_length=100, blank=True)
  67. is_staff = models.BooleanField(
  68. _('职员状态'),
  69. default=False,
  70. help_text=_('指明用户是否可以登录到管理站点。'),
  71. )
  72. is_active = models.BooleanField(
  73. _('激活状态'),
  74. default=True,
  75. help_text=_(
  76. '指明用户是否被认为是活跃的。'
  77. '取消选择此项而不是删除账户。'
  78. ),
  79. )
  80. date_joined = models.DateTimeField(_('注册日期'), default=timezone.now)
  81. # 用户的兴趣标签 (多对多关系)
  82. interests = models.ManyToManyField(
  83. 'InterestTag', # 使用字符串形式引用 InterestTag 模型 (或者将InterestTag定义在CustomUser之前)
  84. verbose_name=_('兴趣标签'),
  85. blank=True, # 允许用户没有任何兴趣标签
  86. related_name='users_with_interest' # 明确的 related_name
  87. )
  88. USERNAME_FIELD = 'email'
  89. REQUIRED_FIELDS = ['phone_number', 'nickname'] # 创建超级用户时需要的额外字段
  90. objects = CustomUserManager() # 关联自定义的 Manager
  91. def __str__(self):
  92. return self.email
  93. @property # 作为一个属性来访问
  94. def display_name(self): # 或者你喜欢的名字,比如 nickname_or_email
  95. return self.nickname if self.nickname else self.email
  96. class Meta:
  97. verbose_name = _('用户')
  98. verbose_name_plural = _('用户们')