Django admin:由信号引起的完整性错误

时间:2018-06-14 14:19:56

标签: django database django-models django-admin

我有一个标准UserProfile模型,其OneToOneField字段到auth.User模型。

每个User必须只有一个UserProfile,因此我需要在创建UserProfile时始终创建User个对象。

显而易见的解决方案是创建一个post_save信号:

@receiver(post_save,sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.get_or_create(user=instance)

问题:

user注册自己或以编程方式创建user时(例如,通过shell),此方法有效。

问题是通过user创建django-admin时。它提出了:

  

重复键值违反了唯一约束   “main_userprofile_user_id_key”DETAIL:Key(user_id)=(30)已经   存在。

我在UserProfile管理页面中添加了User内联,这意味着有两种形式 - 用于User创建和UserProfile创建。

admin.site.unregister(User)


class UserProfileInline(admin.StackedInline):
    model = UserProfile


class UserAdmin(BaseUserAdmin):
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        # (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    #
    ordering = ('username',)
    inlines = [UserProfileInline]
    list_display = ['id', 'username', 'userprofile__display_name','last_login']

现在,当管理员通过user创建新django-admin并填充至少一个UserProfile表单字段时,django会尝试为{{1}创建UserProfile两次返回错误。由user创建后,第二次因为signal表单填写了至少一个表单字段。

你知道怎么做吗?

修改

我会在UserProfile

中添加一个条件
signal

但是在保存管理员的if not getattr(instance,'userprofile'): # create userprofile modelform之前调用了信号,所以它无济于事。

1 个答案:

答案 0 :(得分:0)

我设法将@Chiefir 的建议作为用户代理模型实施:

from django.contrib.auth.models import User

class UserProxy(User):
    class Meta:
        proxy = True

    def save(self):
        UserProfile.objects.get_or_create(user=self)
        super(UserProxy, self).save()

并注释掉信号行:

# signals.post_save.connect(create_profile, sender=User)

另见:https://docs.djangoproject.com/en/3.2/topics/auth/customizing/https://docs.djangoproject.com/en/3.2/topics/db/models/#proxy-models