123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- 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):
- """
- 创建并保存一个具有给定邮箱、手机号和密码的用户。
- """
- print(f"--- CustomUserManager: create_user called ---")
- print(f"Received - Email: {email}, Phone: {phone_number}, Password provided: {'Yes' if password else 'No'}")
- print(f"Received - Extra fields: {extra_fields}")
- if not email:
- print("Validation Error in create_user: Email is required")
- raise ValueError(_('用户必须有一个邮箱地址'))
- if not phone_number:
- print("Validation Error in create_user: Phone number is required")
- raise ValueError(_('用户必须有一个手机号'))
- email = self.normalize_email(email)
- extra_fields.setdefault('is_staff', False)
- extra_fields.setdefault('is_superuser', False)
- # is_active 字段在Admin表单中是可编辑的,所以extra_fields中可能已经有它的值
- # 如果extra_fields中没有is_active,我们再设置默认值
- if 'is_active' not in extra_fields:
- extra_fields.setdefault('is_active', True)
-
- print(f"Normalized email: {email}")
- print(f"Fields for model instance before creation: email={email}, phone_number={phone_number}, extra_fields={extra_fields}")
- user = self.model(email=email, phone_number=phone_number, **extra_fields)
-
- if password:
- user.set_password(password)
- print("Password has been set.")
- else:
- # 对于Admin创建,UserCreationForm应该总是提供密码。
- # 如果通过其他方式调用create_user且没有密码,这里可以记录一个警告或抛出错误。
- print("WARNING in create_user: Password was not provided. User will not be able to log in with a password.")
- try:
- user.save(using=self._db)
- print(f"--- User saved successfully with ID: {user.id} ---")
- except Exception as e:
- print(f"--- ERROR during user.save() in create_user: {e} ---")
- raise # 重新抛出异常,以便Django能捕获
-
- return user
- def create_superuser(self, email, phone_number, password=None, **extra_fields):
- """
- 创建并保存一个具有给定邮箱、手机号和密码的超级用户。
- """
- print(f"--- CustomUserManager: create_superuser called ---")
- print(f"Received - Email: {email}, Phone: {phone_number}, Password provided: {'Yes' if password else 'No'}")
- print(f"Received - Extra fields for superuser: {extra_fields}")
- # create_superuser 应该确保 is_staff 和 is_superuser 为 True
- 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:
- print("Error in create_superuser: is_staff must be True.")
- raise ValueError(_('超级用户必须将 is_staff 设置为 True.'))
- if extra_fields.get('is_superuser') is not True:
- print("Error in create_superuser: is_superuser must be True.")
- raise ValueError(_('超级用户必须将 is_superuser 设置为 True.'))
-
- # 调用 create_user 来完成创建,这样可以复用验证和密码设置逻辑
- # create_user 内部已经有了打印语句
- # 注意:create_user 会将 is_staff 和 is_superuser 设为 False(如果它们不在extra_fields中)
- # 所以我们需要在调用 create_user 后,再把它们强制设为 True。
- # 或者,修改create_user,如果is_staff/is_superuser在extra_fields中提供了,就不覆盖。
- # 当前的create_user是 extra_fields.setdefault,所以如果extra_fields已经有is_staff=True,它不会被覆盖。
-
- # 我们直接调用 create_user,它会处理大部分逻辑
- # 然后确保 is_staff 和 is_superuser 属性是 True (虽然 setdefault 应该已经处理了)
- print(f"Calling create_user from create_superuser with fields: email={email}, phone_number={phone_number}, extra_fields={extra_fields}")
- user = self.create_user(email, phone_number, password, **extra_fields)
-
- # 再次确保超级用户权限 (理论上 setdefault 已经处理,但双重保险)
- # if not user.is_staff or not user.is_superuser:
- # user.is_staff = True
- # user.is_superuser = True
- # try:
- # user.save(using=self._db)
- # print(f"--- Superuser (ID: {user.id}) permissions (is_staff, is_superuser) re-saved ---")
- # except Exception as e:
- # print(f"--- ERROR during superuser permission re-save: {e} ---")
- # raise
-
- return user
- class InterestTag(models.Model):
- 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)
- 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',
- verbose_name=_('兴趣标签'),
- blank=True,
- related_name='users_with_interest'
- )
- USERNAME_FIELD = 'email'
- REQUIRED_FIELDS = ['phone_number', 'nickname']
- objects = CustomUserManager()
- @property
- def display_name(self):
- return self.nickname if self.nickname else self.email
- def __str__(self):
- return self.email
-
- class Meta:
- verbose_name = _('用户')
- verbose_name_plural = _('用户们')
- # 如果有自定义的 save 方法,确保它调用了 super().save()
- # def save(self, *args, **kwargs):
- # print("--- CustomUser save() called ---")
- # # some custom logic
- # super().save(*args, **kwargs) # 确保调用父类的save
- # print("--- CustomUser save() finished ---")
|