【问题标题】:Override the save() method覆盖 save() 方法
【发布时间】:2015-12-30 22:02:49
【问题描述】:

我在 Django 中有一个自定义用户模式,用于处理角色或用户类型,创建一个名为 userprofile 的应用程序,它将设置我的自定义用户模型。

在我的 settings.py 中,我有以下配置:

INSTALLED_APPS = [
        ...
    'userprofile',
]
#Custom model Users
AUTH_USER_MODEL = 'userprofile.User'

我自定义了继承 AbstractUser 类的用户类 (userprofile/models.py),以便根据我的要求向我的用户模型添加一些字段。

我还为角色/个人资料用户 (MedicalProfile, PatientProfile, PhysiotherapistProfile) 创建了这些具有自己的字段或属性的其他模型

此外,MedicalProfile, PatientProfile, PhysiotherapistProfile 与我的自定义模型/类 User 有 OneToOneField 关系,所以:

from __future__ import unicode_literals
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
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)

    # Overriding the save method
    def save(self, *args, **kwargs):
    if self.is_medical:
        profile = MedicalProfile(user=self)
        super(User, self).save(self, *args, **kwargs)
        profile.save()


    # We get the profiles user according with their type
    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)
    #active = models.BooleanField(default=True)
    name = models.CharField(max_length=64)


class PatientProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    #active = models.BooleanField(default=True)
    name = models.CharField(max_length=64)


class PhysiotherapistProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    #active = models.BooleanField(default=True)
    name = models.CharField(max_length=64)

我的问题

我想把我的问题集中在覆盖过程save() 方法上:

def save(self, *args, **kwargs):
    if self.is_medical:
        profile = MedicalProfile(user=self)
        super(User, self).save(self, *args, **kwargs)
        profile.save()

我希望,每个创建用户时,根据他们的字段是否检查(is_medical、is_patient、is_physiotherapy)自动创建他们的个人资料(MedicalProfile、PatientProfile、PhysiotherapyProfile)

我的覆盖过程带来的不便如下:

  • 当我通过 django admin 创建用户时,出现此错误

我不知道,关于将用户 PK 设置为无的原因...

我可以有什么替代方案来解决这种情况,当我创建用户时,他们的个人资料实例会根据我选择的属性复选框/字段(is_medical、is_physiotherapy、is_patient)被保存(MedicalProfile、PhysiotherapyProfile、PatientProfile)?

如果我的问题不适合或不适合 stackoverflow 哲学或我的问题的范围,我会向您道歉。

之所以说得这么详细,是因为我想提供所有细节以获得答案

任何方向我将不胜感激,将不胜感激

【问题讨论】:

  • 你到底为什么要发布所有这些代码截图?你为什么这样做?代码是text,就这样贴出来吧。
  • 好吧@DanielRoseman,你有理由。我确实为它们各自的代码更改了模型类图像,编辑了我的问题。关于与调试过程相关的另一个图像......我可以留下图像吗,因为在它们中我想参考我的调试过程的内容。没事吧?
  • 我认为最简单和更好的方法是覆盖我的用户模型上的保存方法。我试试docs.djangoproject.com/en/1.9/topics/db/models/…
  • 我正在尝试覆盖保存方法,但我遇到了一个问题,我在上面的问题中进行了编辑...

标签: python django django-admin


【解决方案1】:

如果用户不是医疗人员,你需要在你的保存方法中做一些事情;您仍然需要实际保存对象。

一个固定的实现是:

def save(self, *args, **kwargs):
    user = super(User, self).save(self, *args, **kwargs)
    if self.is_medical:
        MedicalProfile(user=self).save()

【讨论】:

    【解决方案2】:

    我位于userprofile/models.pyclass User 覆盖了保存方法,保持不变:

    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 save(self, *args, **kwargs):
            user = super(User, self).save( *args, **kwargs)
    
            # Creating and user with medical, patient and physiotherapist profiles
            if self.is_medical and not MedicalProfile.objects.filter(user=self).exists()\
                    and self.is_patient and not PatientProfile.objects.filter(user=self).exists()\
                    and self.is_physiotherapist and not PhysiotherapistProfile.objects.filter(user=self).exists():
    
                medical_profile=MedicalProfile(user=self).save()
                patient_profile=PatientProfile(user=self).save()
                physiotherapist_profile=PhysiotherapistProfile(user=self).save()
                #profile.save()
    
            # Creating and user with medical and patient profiles
            elif self.is_medical and not MedicalProfile.objects.filter(user=self).exists()\
                and self.is_patient and not PatientProfile.objects.filter(user=self).exists():
    
                medical_profile=MedicalProfile(user=self).save()
                patient_profile=PatientProfile(user=self).save()
    
            # Creating and user with medical and physiotherapist profiles
            elif self.is_medical and not MedicalProfile.objects.filter(user=self).exists()\
                and self.is_physiotherapist and not PhysiotherapistProfile.objects.filter(user=self).exists():
    
                medical_profile=MedicalProfile(user=self).save()
                physiotherapist_profile=PhysiotherapistProfile(user=self).save()
    
            # Creating and user with physiotherapist and patient profiles
            elif self.is_physiotherapist and not PhysiotherapistProfile.objects.filter(user=self).exists()\
                and self.is_patient and not PatientProfile.objects.filter(user=self).exists():
    
                physiotherapist_profile = PhysiotherapistProfile(user=self).save()
                patient_profile = PatientProfile(user=self).save()
    
            # Creating and user with medical profile
            elif self.is_medical and not MedicalProfile.objects.filter(user=self).exists():
                profile = MedicalProfile(user=self)
                profile.save()
    
            # Creating and user with patient profile
            elif self.is_patient and not PatientProfile.objects.filter(user=self).exists():
                profile = PatientProfile(user=self)
                profile.save()
    
            # Creating and user with physiotherapist profiles
            elif self.is_physiotherapist and not PhysiotherapistProfile.objects.filter(user=self).exists():
                profile = PhysiotherapistProfile(user=self)
                profile.save()
    
    
    
        # We get the profiles user according with their type
        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
    
        # We redefine the attributes (create db_table attribute) in class Meta to say to Django
        # that users will save in the same table that the Django default user model
        # https://github.com/django/django/blob/master/django/contrib/auth/models.py#L343
        class Meta:
    
            db_table = 'auth_user'
    
    class MedicalProfile(models.Model):
        user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        #active = models.BooleanField(default=True)
        name = models.CharField(max_length=64)
    
    
    class PatientProfile(models.Model):
        user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        #active = models.BooleanField(default=True)
        name = models.CharField(max_length=64)
    
    
    class PhysiotherapistProfile(models.Model):
        user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        #active = models.BooleanField(default=True)
        name = models.CharField(max_length=64)
    
    # Enter the username as slug field
    @receiver(post_save, sender = settings.AUTH_USER_MODEL)
    def post_save_user(sender, instance, **kwargs):
        slug = slugify(instance.username)
        User.objects.filter(pk=instance.pk).update(slug=slug)
    

    save() 方法让我用所有可能的配置文件组合保存用户。

    但是,有没有更好的方法来做到这一点?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-28
      • 2021-11-21
      • 2018-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-08
      • 2013-04-23
      相关资源
      最近更新 更多