我正在按照'User profile'方法扩展我的用户模型,如下所示:
# models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE, primary_key=True)
my_field = models.CharField(max_length=100)
# signals.py
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
通过这种方法,我必须明确地调用user.profile.save()
,这让我感到笨拙,因为我希望profile
给出幻觉它是User
对象的一部分:< / p>
# views.py
def some_func(request):
user = User.objects.create_user('dummy', 'dummy@dummy.com', '12345678')
user.profile.my_field = 'hello'
user.save() # This does not persist the profile object...
user.profile.save() # ...this does
为了解决这个问题,我已将create_user_profile()
更改为以下内容,其中有效:
# signals.py
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
profile = UserProfile.objects.get_or_create(user=instance)
profile.save()
我遇到的很多例子都不使用这种方法。使用这种方法有什么警告吗?
答案 0 :(得分:3)
更好的方法是指定自定义用户模型。
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
custom_field = models.ForeignKey(
'contracts.Contract'
)
...
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
您必须更新定义settings.py
属性的AUTH_USER_MODEL
:
AUTH_USER_MODEL = 'app_name.User'
答案 1 :(得分:1)
您可以使用这样的自定义用户模型:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return f'{self.user.username} Profile'
,然后是signals.py文件:
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
这里的signals.py文件的作用是通知您何时创建了一个用户类型的新Profile对象,您可以将其进一步用于创建更新/创建用户个人资料的表单。
要使所有这些工作正常进行,您需要在应用程序的apps.py文件中导入signals.py文件。例如,这是您的apps.py文件的外观:
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
答案 2 :(得分:0)
是的,有一些。在以下情况下,不会触发post_save信号。
1如果save方法未成功保存对象(例如发生IntegrityError时)
2致电MyModel.objects.update()
3覆盖save方法时忘记调用超类方法。
4当您的信号接收器尚未成功注册时。
在这些情况下,您的个人资料不会被保存。