Django:Django Admin中具有唯一外键的UserProfile

时间:2010-05-11 18:01:00

标签: django inline admin django-signals foreign-keys

我使用名为UserExtension的自定义用户个人资料扩展了Django的用户模型。 它通过一个独特的ForeignKey Relationship与User相关,这使我能够以内嵌形式在admin中编辑它! 我正在使用信号为每个新用户创建一个新的配置文件:

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) 

(如此处所述:Extending the User model with custom fields in Django) 问题是,如果我通过管理员创建一个新用户,我会在保存“列user_id不唯一”时遇到IntegritiyError。似乎信号被调用两次,但我想管理员试图保存配置文件AFTERWARDS? 但是如果我在系统的其他部分创建一个新用户,我需要通过信号创建!

1 个答案:

答案 0 :(得分:15)

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

  1. 创建用户对象
  2. 创建个人资料对象(之前不能指向用户)。
  3. 当保存用户对象时,django ORM无法知道创建配置文件对象将在它之后,因此它不会以任何方式延迟post_save信号(甚至没有意义)。

    如果你想保留post_save信号,处理这个(imho)的最佳方法是将UserExtension的保存方法覆盖为:

    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)
    

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