models.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. print(f"--- CustomUserManager: create_user called ---")
  14. print(f"Received - Email: {email}, Phone: {phone_number}, Password provided: {'Yes' if password else 'No'}")
  15. print(f"Received - Extra fields: {extra_fields}")
  16. if not email:
  17. print("Validation Error in create_user: Email is required")
  18. raise ValueError(_('用户必须有一个邮箱地址'))
  19. if not phone_number:
  20. print("Validation Error in create_user: Phone number is required")
  21. raise ValueError(_('用户必须有一个手机号'))
  22. email = self.normalize_email(email)
  23. extra_fields.setdefault('is_staff', False)
  24. extra_fields.setdefault('is_superuser', False)
  25. # is_active 字段在Admin表单中是可编辑的,所以extra_fields中可能已经有它的值
  26. # 如果extra_fields中没有is_active,我们再设置默认值
  27. if 'is_active' not in extra_fields:
  28. extra_fields.setdefault('is_active', True)
  29. print(f"Normalized email: {email}")
  30. print(f"Fields for model instance before creation: email={email}, phone_number={phone_number}, extra_fields={extra_fields}")
  31. user = self.model(email=email, phone_number=phone_number, **extra_fields)
  32. if password:
  33. user.set_password(password)
  34. print("Password has been set.")
  35. else:
  36. # 对于Admin创建,UserCreationForm应该总是提供密码。
  37. # 如果通过其他方式调用create_user且没有密码,这里可以记录一个警告或抛出错误。
  38. print("WARNING in create_user: Password was not provided. User will not be able to log in with a password.")
  39. try:
  40. user.save(using=self._db)
  41. print(f"--- User saved successfully with ID: {user.id} ---")
  42. except Exception as e:
  43. print(f"--- ERROR during user.save() in create_user: {e} ---")
  44. raise # 重新抛出异常,以便Django能捕获
  45. return user
  46. def create_superuser(self, email, phone_number, password=None, **extra_fields):
  47. """
  48. 创建并保存一个具有给定邮箱、手机号和密码的超级用户。
  49. """
  50. print(f"--- CustomUserManager: create_superuser called ---")
  51. print(f"Received - Email: {email}, Phone: {phone_number}, Password provided: {'Yes' if password else 'No'}")
  52. print(f"Received - Extra fields for superuser: {extra_fields}")
  53. # create_superuser 应该确保 is_staff 和 is_superuser 为 True
  54. extra_fields.setdefault('is_staff', True)
  55. extra_fields.setdefault('is_superuser', True)
  56. extra_fields.setdefault('is_active', True) # 超级用户默认激活
  57. if extra_fields.get('is_staff') is not True:
  58. print("Error in create_superuser: is_staff must be True.")
  59. raise ValueError(_('超级用户必须将 is_staff 设置为 True.'))
  60. if extra_fields.get('is_superuser') is not True:
  61. print("Error in create_superuser: is_superuser must be True.")
  62. raise ValueError(_('超级用户必须将 is_superuser 设置为 True.'))
  63. # 调用 create_user 来完成创建,这样可以复用验证和密码设置逻辑
  64. # create_user 内部已经有了打印语句
  65. # 注意:create_user 会将 is_staff 和 is_superuser 设为 False(如果它们不在extra_fields中)
  66. # 所以我们需要在调用 create_user 后,再把它们强制设为 True。
  67. # 或者,修改create_user,如果is_staff/is_superuser在extra_fields中提供了,就不覆盖。
  68. # 当前的create_user是 extra_fields.setdefault,所以如果extra_fields已经有is_staff=True,它不会被覆盖。
  69. # 我们直接调用 create_user,它会处理大部分逻辑
  70. # 然后确保 is_staff 和 is_superuser 属性是 True (虽然 setdefault 应该已经处理了)
  71. print(f"Calling create_user from create_superuser with fields: email={email}, phone_number={phone_number}, extra_fields={extra_fields}")
  72. user = self.create_user(email, phone_number, password, **extra_fields)
  73. # 再次确保超级用户权限 (理论上 setdefault 已经处理,但双重保险)
  74. # if not user.is_staff or not user.is_superuser:
  75. # user.is_staff = True
  76. # user.is_superuser = True
  77. # try:
  78. # user.save(using=self._db)
  79. # print(f"--- Superuser (ID: {user.id}) permissions (is_staff, is_superuser) re-saved ---")
  80. # except Exception as e:
  81. # print(f"--- ERROR during superuser permission re-save: {e} ---")
  82. # raise
  83. return user
  84. class InterestTag(models.Model):
  85. name = models.CharField(
  86. _('标签名称'),
  87. max_length=50,
  88. unique=True,
  89. help_text=_('兴趣标签的名称,例如:摄影、篮球、Python编程')
  90. )
  91. created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('创建时间'))
  92. class Meta:
  93. verbose_name = _('兴趣标签')
  94. verbose_name_plural = _('兴趣标签们')
  95. ordering = ['name']
  96. def __str__(self):
  97. return self.name
  98. class CustomUser(AbstractBaseUser, PermissionsMixin):
  99. email = models.EmailField(_('邮箱地址'), unique=True)
  100. phone_number = models.CharField(_('手机号'), max_length=20, unique=True)
  101. nickname = models.CharField(_('昵称'), max_length=100, blank=True)
  102. avatar = models.ImageField(_('头像'), upload_to='avatars/', null=True, blank=True)
  103. bio = models.TextField(_('简介'), blank=True)
  104. school = models.CharField(_('学校'), max_length=100, blank=True)
  105. is_staff = models.BooleanField(
  106. _('职员状态'),
  107. default=False,
  108. help_text=_('指明用户是否可以登录到管理站点。'),
  109. )
  110. is_active = models.BooleanField(
  111. _('激活状态'),
  112. default=True, # 默认用户是激活的
  113. help_text=_(
  114. '指明用户是否被认为是活跃的。'
  115. '取消选择此项而不是删除账户。'
  116. ),
  117. )
  118. date_joined = models.DateTimeField(_('注册日期'), default=timezone.now)
  119. interests = models.ManyToManyField(
  120. 'InterestTag',
  121. verbose_name=_('兴趣标签'),
  122. blank=True,
  123. related_name='users_with_interest'
  124. )
  125. USERNAME_FIELD = 'email'
  126. REQUIRED_FIELDS = ['phone_number', 'nickname']
  127. objects = CustomUserManager()
  128. @property
  129. def display_name(self):
  130. return self.nickname if self.nickname else self.email
  131. def __str__(self):
  132. return self.email
  133. class Meta:
  134. verbose_name = _('用户')
  135. verbose_name_plural = _('用户们')
  136. # 如果有自定义的 save 方法,确保它调用了 super().save()
  137. # def save(self, *args, **kwargs):
  138. # print("--- CustomUser save() called ---")
  139. # # some custom logic
  140. # super().save(*args, **kwargs) # 确保调用父类的save
  141. # print("--- CustomUser save() finished ---")