4

我将 Django 1.4.1 与 postgresql 9.1 一起使用。

我需要向使用 auth 应用程序提供的用户添加配置文件,并允许管理应用程序创建和编辑此配置文件。因此,我一直在关注文档部分存储有关用户的附加信息

模型.py

class UserProfile(models.Model):
    user = models.OneToOneField(User)

    bio = models.TextField(null = True, blank = True)
    contact = models.TextField(null = True, blank = True)

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

post_save.connect(create_user_profile, sender=User)

设置.py

...
AUTH_PROFILE_MODULE = 'userprofile.UserProfile'
...

django.contrib.auth我还激活django.contrib.adminINSTALLED_APPS.

管理员.py

class UserProfileInline(admin.StackedInline):
    model = UserProfile
    can_delete = False
    verbose_name_plural = 'profile'

class UserAdmin(UserAdmin):
    inlines = (UserProfileInline, )

# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

问题

现在,当我运行管理应用程序并要求添加(创建)一个新用户时,我被要求通过两步过程创建我的用户:首先,一个页面只要求输入用户名、密码(两次)和我的两个 UserProfile 字段。

如果我只输入用户名和密码(两次)并单击“保存”,我会看到该过程的第二页,它允许填写所有其他用户字段以及我的 UserProfile 字段。有一条消息说“用户“xxxxx”已成功添加。您可以在下面再次编辑它。”,幸运的是我可以编辑两个模型的字段,它有效。

但是,如果我尝试在第一页的一个或两个 UserProfile 字段中输入任何内容,则提交失败并显示以下消息:

IntegrityError at /admin/auth/user/add/

duplicate key value violates unique constraint "userprofile_userprofile_user_id_key"
DETAIL:  Key (user_id)=(7) already exists.

每次我尝试时,“7”都会增加。

如何避免这种行为,或者如何防止配置文件字段在第一页中可编辑,但让它们在第二页中进行编辑?

完整追溯:

环境:

请求方法:POST
请求网址:http://127.0.0.1:8000/admin/auth/user/add/

Django 版本:1.4.1
Python版本:2.7.3
已安装的应用程序:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'django.contrib.admindocs',
 '用户资料')
已安装的中间件:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')

追溯:
get_response 中的文件“/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py”
  111. 响应 = 回调(请求,*callback_args,**callback_kwargs)
包装器中的文件“/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py”
  366. return self.admin_site.admin_view(view)(*args, **kwargs)
_wrapped_view 中的文件“/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py”
  91. 响应 = view_func(请求,*args,**kwargs)
_wrapped_view_func 中的文件“/usr/local/lib/python2.7/dist-packages/django/views/decorators/cache.py”
  89. 响应 = view_func(请求,*args,**kwargs)
内部文件“/usr/local/lib/python2.7/dist-packages/django/contrib/admin/sites.py”
  196. 返回视图(请求,*args,**kwargs)
在sensitive_post_parameters_wrapper 文件“/usr/local/lib/python2.7/dist-packages/django/views/decorators/debug.py”
  69. 返回视图(请求,*args,**kwargs)
_wrapper 中的文件“/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py”
  25. 返回 bound_func(*args, **kwargs)
_wrapped_view 中的文件“/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py”
  91. 响应 = view_func(请求,*args,**kwargs)
bound_func 中的文件“/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py”
  21. 返回函数(自我,*args2,**kwargs2)
内部文件“/usr/local/lib/python2.7/dist-packages/django/db/transaction.py”
  209. 返回函数(*args, **kwargs)
add_view 中的文件“/usr/local/lib/python2.7/dist-packages/django/contrib/auth/admin.py”
  114.extra_context)
_wrapper 中的文件“/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py”
  25. 返回 bound_func(*args, **kwargs)
_wrapped_view 中的文件“/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py”
  91. 响应 = view_func(请求,*args,**kwargs)
bound_func 中的文件“/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py”
  21. 返回函数(自我,*args2,**kwargs2)
内部文件“/usr/local/lib/python2.7/dist-packages/django/db/transaction.py”
  209. 返回函数(*args, **kwargs)
add_view 中的文件“/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py”
  956. self.save_related(request, form, formsets, False)
save_related 中的文件“/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py”
  733. self.save_formset(请求,表单,表单集,更改=更改)
save_formset 中的文件“/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py”
  721. formset.save()
保存文件“/usr/local/lib/python2.7/dist-packages/django/forms/models.py”
  497. return self.save_existing_objects(commit) + self.save_new_objects(commit)
save_new_objects 中的文件“/usr/local/lib/python2.7/dist-packages/django/forms/models.py”
  628. self.new_objects.append(self.save_new(form, commit=commit))
save_new 中的文件“/usr/local/lib/python2.7/dist-packages/django/forms/models.py”
  731. obj.save()
保存文件“/usr/local/lib/python2.7/dist-packages/django/db/models/base.py”
  463. self.save_base(使用=使用,force_insert=force_insert,force_update=force_update)
save_base 中的文件“/usr/local/lib/python2.7/dist-packages/django/db/models/base.py”
  551. 结果 = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
_insert 中的文件“/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py”
  203. return insert_query(self.model, objs, fields, **kwargs)
insert_query 中的文件“/usr/local/lib/python2.7/dist-packages/django/db/models/query.py”
  1576. return query.get_compiler(using=using).execute_sql(return_id)
execute_sql 中的文件“/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py”
  910. cursor.execute(sql,参数)
执行中的文件“/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py”
  40. return self.cursor.execute(sql, params)
执行中的文件“/usr/local/lib/python2.7/dist-packages/django/db/backends/postgresql_psycopg2/base.py”
  52.返回self.cursor.execute(查询,参数)

异常类型:/admin/auth/user/add/ 处的 IntegrityError
异常值:重复键值违反唯一约束“userprofile_userprofile_user_id_key”
详细信息:键 (user_id)=(7) 已存在。`
4

3 回答 3

4

代替

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

做一个

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

您正在创建新的用户配置文件对象,即使是用于编辑。

于 2012-10-08T15:38:50.587 回答
4

正如评论中提到的 CadentOrange ,此答案中描述了此问题的解决方案。

问题在于使用内联管理表单。这是发生的事情:

  1. 它保存了主模型 ( User)
  2. 由于(1),触发了post_save信号处理程序,从而创建了一个新对象UserUserProfile
  3. 每个内联模型都被保存(包括你的另一个副本UserProfile,导致欺骗)。
于 2013-06-11T15:54:51.657 回答
2

create_user_profile信号和管理表单尝试创建相同的用户配置文件。您可以覆盖LocalUserAdminUserProfileInline从添加视图中排除:

class LocalUserAdmin(UserAdmin):
    inlines = (UserProfileInline, )

    def get_formsets_with_inlines(self, request, obj=None):
        for inline in self.get_inline_instances(request, obj):
            # hide MyInline in the add view
            if isinstance(inline, UserProfileInline) and obj is None:
                continue
            yield inline.get_formset(request, obj), inline

https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_formsets_with_inlines

于 2013-01-22T09:19:48.543 回答