首页 文章

填写配置文件字段时,管理员中的Django用户创建失败

提问于
浏览
4

我正在使用带有postgresql 9.1的Django 1.4.1 .

我需要向使用auth应用程序的用户添加配置文件,并允许管理员应用程序创建和编辑此配置文件 . 因此,我一直在关注文档部分Storing additional information about users

models.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)

settings.py

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

我还在 INSTALLED_APPS 中激活了 django.contrib.authdjango.contrib.admin 应用程序 .

admin.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)

问题

现在,当我运行管理员应用程序并要求添加(创建)新用户时,我被要求通过 two-step process 创建我的用户:首先,一个页面只询问用户名,密码(两次)和我的两个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”都会递增 .

How can that behavior be avoided, or alternatively how can I prevent the profile fields to be editable in the first page, but letting them be edited in the second page ?

完全追溯:

Environment:

Request Method: POST
Request URL: http://127.0.0.1:8000/admin/auth/user/add/

Django Version: 1.4.1
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'django.contrib.admindocs',
 'userprofile')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')

Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in wrapper
  366.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
  91.                     response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func
  89.         response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/sites.py" in inner
  196.             return view(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/debug.py" in sensitive_post_parameters_wrapper
  69.             return view(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapper
  25.             return bound_func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
  91.                     response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in bound_func
  21.                 return func(self, *args2, **kwargs2)
File "/usr/local/lib/python2.7/dist-packages/django/db/transaction.py" in inner
  209.                 return func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/auth/admin.py" in add_view
  114.                                                extra_context)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapper
  25.             return bound_func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
  91.                     response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in bound_func
  21.                 return func(self, *args2, **kwargs2)
File "/usr/local/lib/python2.7/dist-packages/django/db/transaction.py" in inner
  209.                 return func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in add_view
  956.                 self.save_related(request, form, formsets, False)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in save_related
  733.             self.save_formset(request, form, formset, change=change)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in save_formset
  721.         formset.save()
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py" in save
  497.         return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py" in save_new_objects
  628.             self.new_objects.append(self.save_new(form, commit=commit))
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py" in save_new
  731.             obj.save()
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in save
  463.         self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in save_base
  551.                 result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py" in _insert
  203.         return insert_query(self.model, objs, fields, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py" in insert_query
  1576.     return query.get_compiler(using=using).execute_sql(return_id)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py" in execute_sql
  910.             cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py" in execute
  40.             return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/postgresql_psycopg2/base.py" in execute
  52.             return self.cursor.execute(query, args)

Exception Type: IntegrityError at /admin/auth/user/add/
Exception Value: duplicate key value violates unique constraint "userprofile_userprofile_user_id_key"
DETAIL:  Key (user_id)=(7) already exists.`

3 回答

  • 4

    正如CadentOrange在评论中提到的那样,这个问题的解决方案在this answer中有所描述 .

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

    • 保存主模型( User

    • 由于(1), Userpost_save 信号处理程序被触发,这将创建一个新的 UserProfile 对象

    • 保存每个内联模型(包括 UserProfile 的另一个副本,导致欺骗) .

  • 5

    代替

    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)
    

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

  • 2

    create_user_profile 信号和管理表单尝试创建相同的UserProfile . 您可以覆盖 LocalUserAdmin 以从添加视图中排除 UserProfileInline

    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

相关问题