我有一个派生自 AbstractUser 类的用户角色模式(医疗、患者、物理治疗师),以便在请求中使用它,如以下模型所示:
#models.py
from __future__ import unicode_literals
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.contrib.auth import get_user_model
from django.dispatch import receiver
from django.db.models.signals import post_save
class User(AbstractUser):
is_medical = models.BooleanField(default=False)
is_physiotherapist = models.BooleanField(default=False)
is_patient = models.BooleanField(default=False)
slug = models.SlugField(max_length=100, blank=True)
photo = models.ImageField(upload_to='avatars', null = True, blank = True)
def get_medical_profile(self):
medical_profile = None
if hasattr(self, 'medicalprofile'):
medical_profile=self.medicalprofile
return medical_profile
def get_patient_profile(self):
patient_profile = None
if hasattr(self, 'patientprofile'):
patient_profile = self.patientprofile
return patient_profile
def get_physiotherapist_profile(self):
physiotherapist_profile = None
if hasattr(self, 'physiotherapistprofile'):
physiotherapist_profile = self.physiotherapistprofile
return physiotherapist_profile
class Meta:
db_table = 'auth_user'
class MedicalProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=64)
class PatientProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=64)
class PhysiotherapistProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=64)
我想要的是,当一个新用户被自动创建时,如果他是医生、病人或物理治疗师,他的个人资料会根据他的领域创建(is_medical
, is_patient
, is_physiotherapist
)
为此,我post_save()
在我的模型所在的同一个 models.py 文件中以下列方式使用信号:
在信号中,我发送三个参数加上 **kwargs:
sender
,这是我的用户模型created
,一个布尔参数,告诉我我的用户模型的一个实例AUTH_USER_MODEL
已经创建instance
,正在创建的用户实例
要知道即将创建一个用户,我必须以某种方式找出在我提出的那个请求(创建用户)中,那个用户或那个即将被创建的实例是否存在,为此我做了user = self.request.user
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_profile_for_new_user(sender, created, instance, **kwargs):
# Pregunto si en el request va el user, aqui va mi inquietud
user = self.request.user
#user = get_user_model()
if created:
if user.is_medical:
profile=MedicalProfile(user=instance)
profile.save()
这是一个很好的逻辑,但事实证明我还没有定义 self 并且我(显然)得到了这个错误
在create_profile_for_new_user(...)
我应用信号的方法中,post_save()
我只有四个属性,所以如果我在开头添加 self 作为属性
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_profile_for_new_user(self,sender, created, instance, **kwargs):
会得到这个错误:
TypeError: create_profile_for_new_user() missing 1 required positional argument: 'self'
127.0.0.1 - - [28/Dec/2015 22:57:04] "GET /admin/userprofile/user/add/?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
我正在考虑的另一个选择是获取正在使用该功能创建的用户,get_user_model()
就像我在这里所做的那样(当然之前导入了该功能from django.contrib.auth import get_user_model
):
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_profile_for_new_user(sender, created, instance, **kwargs):
# Pregunto si en el request va el user, aqui va mi inquietud
#user = self.request.user
user = get_user_model()
if created:
if user.is_medical:
profile=MedicalProfile(user=instance)
profile.save()
但是当我这样做时,我收到了这条消息,这是合乎逻辑的,因为在这种情况下,我的 User 对象(我正在获取原始 Django User 模型的一个实例)没有我要求的属性is_medical
根据上述,我不知道如何询问或询问用户以检查他们的布尔属性(is_patient
, is_medical
, is_physiotherapist
)并相应地创建他们各自的配置文件。
顺便说一句,我利用了另一个问题:是否可以将信号post_save
用于多个目的?
在这种情况下,我想使用它来创建创建的用户实例的配置文件,并slug
根据其属性为命名字段赋予值first_name
。也就是说,你能把它应用到你需要的方法上吗?
请记住,它
create_profile_for_new_user
是与模型相关的功能,而不是视图,因此您无权访问request
. 它也不是一门课程,因此您无法随心所欲地访问它self
。该参数
created
不会按您的意愿工作,因为您在错误的参数位置使用它,接收信号的函数的第一个参数是发送信号的模型 (sender
),第二个参数是该模型的实例(instance
)。该参数
instance
是包含已创建用户的参数,因此以下内容有效:甚至没有必要,您可以在不需要分配变量的情况下做到这一点
user
:如果您需要分配模型的其他字段,您也可以这样做,尽管我认为我们已经解决了这个问题:
笔记:
请注意,在所有示例中,我都没有使用
created
您最初定义为参数的参数。虽然可以使用
created
del参数post_save
,但请注意这是第三个参数,而不是第二个:更新:
您在评论中提到的问题
IntegrityError
是因为当您登录时,系统正在尝试保存您的上次登录日期,并且在尝试执行此操作时,它会再次调用post_save
您的函数create_profile_for_new_user
。解决方案是始终使用参数
created
:如果您不使用它,该函数将尝试再次保存配置文件并生成一个
IntegrityError
,因为配置文件是在最初创建用户之前创建的。在 settings.py 文件中,您必须在AUTH_USER_MODEL属性中指定从 AbstractUser 继承的类。 所以它会是
这将采用您的类的实例,而不是默认的用户类 (auth.User)
最后,我选择通过覆盖
save()
类方法AbstractUser
而不是通过将信号post_save()
应用于函数来工作,create_profile_for_new_user
所以我的模型看起来像这样:User
MedicalProfile
PatientProfile
PhisiotherapystProfile
通过这种方式,可以创建具有所有可能的角色组合(医生、患者、物理治疗师)的用户。
无论如何,
post_save()
在函数中应用的信号仍然用于在模型中的post_save_user()
我的字段中输入 slug 值。此值基于属性slug
User
username
非常感谢您一直以来的指导。:)