Django:Django 管理中具有唯一外键的用户配置文件

发布于 2024-08-31 23:46:42 字数 695 浏览 7 评论 0原文

我使用名为 UserExtension 的自定义用户配置文件扩展了 Django 的用户模型。 它通过独特的外键关系与用户相关,这使我能够以内联形式在管理中编辑它! 我正在使用信号为每个新用户创建新的配置文件:(

def create_user_profile(sender, instance, created, **kwargs):  
    if created:
        try:  
            profile, created = UserExtension.objects.get_or_create(user=instance)
        except:
            pass  

post_save.connect(create_user_profile, sender=User) 

如此处所述,例如: 使用 Django 中的自定义字段扩展用户模型) 问题是,如果我通过管理员创建一个新用户,我会在保存“列 user_id 不唯一”时收到 IntegritiyError 。信号似乎没有被调用两次,但我猜管理员正在尝试事后保存配置文件? 但是如果我在系统的其他部分创建新用户,我需要通过信号创建!

I have extended Django's User Model using a custom user profile called UserExtension.
It is related to User through a unique ForeignKey Relationship, which enables me to edit it in the admin in an inline form!
I'm using a signal to create a new profile for every new user:

def create_user_profile(sender, instance, created, **kwargs):  
    if created:
        try:  
            profile, created = UserExtension.objects.get_or_create(user=instance)
        except:
            pass  

post_save.connect(create_user_profile, sender=User) 

(as described here for example: Extending the User model with custom fields in Django)
The problem is, that, if I create a new user through the admin, I get an IntegritiyError on saving "column user_id is not unique". It doesnt seem that the signal is called twice, but i guess the admin is trying to save the profile AFTERWARDS?
But I need the creation through signal if I create a new user in other parts of the system!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

狼性发作 2024-09-07 23:46:42

django 之后创建管理实例是正常的,因为保存总是包含这样的内容:

  1. 创建用户对象
  2. 创建配置文件对象(不能在之前,因为它指向用户)。

当保存 User 对象时,django ORM 无法知道创建配置文件对象会在它之后,因此它不会以任何方式延迟 post_save 信号(甚至没有意义)。

如果您想保留 post_save 信号,处理此问题的最佳方法(恕我直言)是将 UserExtension 的 save 方法重写为如下所示:

def save(self, *args, **kwargs):
    try:
        existing = UserExtension.objects.get(user=self.user)
        self.id = existing.id #force update instead of insert
    except UserExtension.DoesNotExist:
        pass 
    models.Model.save(self, *args, **kwargs)

请注意,这确实会强制每个指向相同的插入用户作为现有对象进行更新,这对于代码的其他部分来说可能是意外的行为。

It is normal that django will create the admin instance afterwards, as the saving consists always of something like this:

  1. Create User object
  2. Create Profile object (can't be before because it points to a user).

When saving the User object the django ORM cannot know the create profile object will come after it so it will not delay the post_save signal in any way (doesn't even make sense).

The best way to handle this (imho) if you want to keep the post_save signal, is to override the save method of UserExtension to something like this:

def save(self, *args, **kwargs):
    try:
        existing = UserExtension.objects.get(user=self.user)
        self.id = existing.id #force update instead of insert
    except UserExtension.DoesNotExist:
        pass 
    models.Model.save(self, *args, **kwargs)

Note that this does force every insert that points to the same user as an existing object to become an update, this can be unexpected behaviour for other parts of code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文