Django user does not work when creating profile fields.

I am using Django 1.4.1 with postgresql 9.1.

I need to add a profile to the user specified in the auth application and allow the admin application to create and edit this profile. Thus, I am following the docs section Storing additional user information :

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' ... 

I also activated the django.contrib.auth and django.contrib.admin in INSTALLED_APPS .

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) 

Problem

Now, when I started the application for the administrator and asked to add (create) a new user, I will be asked to create my user through a two-step process : firstly, a page requesting only the username, password (twice) and two of my UserProfile fields.

If I type only the username and password (twice) and click "Save", I show the second page of the process, which allows you to fill in all other fields of the user, as well as UserProfile fields. There was added the message "User" xxxxx ". You can edit it again below," and, fortunately, I can edit the fields from both models, it works.

But if I try to enter something in one or both of my UserProfile fields on the first page, the message will fail with the message:

 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" increases every time I try.

How to avoid this behavior or, as an alternative, how can I prevent editing of the profile fields on the first page, but allow them to be edited on the second page?

Full trace:

  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.`
+4
source share
3 answers

As CadentOrange mentions in a comment, a solution to this problem is described in this answer .

The problem is using the built-in admin form. Here's what happens:

  • Saves the main model ( User )
  • In connection with (1), the post_save signal post_save for User started, which creates a new UserProfile object
  • Each built-in model is saved (including another copy of your UserProfile , which leads to cheating).
+4
source

instead

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

follow

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

You create a new user profile object even for editing.

+5
source

I think the problem is how admin store models are stored by default. I had a simulated problem and it was solved by disabling the built-in lines for the user model as follows:

 class LocalUserAdmin(UserAdmin): inlines = (UserProfileInline, ) def get_formsets(self, request, obj=None): if not obj: return [] return super(LocalUserAdmin, self).get_formsets(request, obj) 
+1
source

Source: https://habr.com/ru/post/1438445/


All Articles