4

I have a model called UserProfile which stores additional data about a django user.

This model has a OneToOneField to django.contrib.auth.models.User

I also have a post save signal on a User object that is fired on initial insert of a User which creates a UserProfile object linked to that User:

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

post_save.connect(create_user_profile, sender=User)

User objects can be created via the website front end which when saved creates the UserProfile. This all works fine.

I also have an admin.py file that allows a User and UserProfile object to be created via the admin console:

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from myproject.apps.users.models import UserProfile

admin.site.unregister(User)


class UserProfileInline(admin.StackedInline):
    model = UserProfile
    filter_horizontal = ['companies']
    exclude = [
        'field_1', field_n'
    ]


class UserProfileAdmin(UserAdmin):
    inlines = [UserProfileInline]

admin.site.register(User, UserProfileAdmin)

When creating a new User via the admin console, the UserProfile form is displayed below the User form. If I leave all UserProfile fields as default (i.e. do not enter any data into the form fields or change any default values) the User is created successfully with the UserProfile. If however I attempt to add any values or update any defaults in the UserProfile form it falls over with the error:

IntegrityError at /admin/auth/user/add/

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

This indicates the post_save signal on the User object has been called twice, both times the created flag that has been passed into the signal has been set to True resulting in an attempt in inserting a UserProfile object twice with the same User id. Django ends up rolling back the transaction and neither the User or UserProfile objects are inserted.

To add a bizarre twist if I completely remove the post_save signal everything works fine in the admin console and django appears to magically create the UserProfile object for me without even (apparently) knowing about it. Obviously this then breaks the front end as it relies on this post_save signal to create the UserProfile object.

I'm running Django 1.6 using PostgreSQL.

Any shedding of light on this situation would be hugely appreciated. Otherwise I think another approach to how the UserProfile is managed in the admin console will have to be considered.

chewynougat
  • 1,099
  • 2
  • 11
  • 19
  • 3
    Problem looks like: http://stackoverflow.com/questions/14345303/creating-a-profile-model-with-both-an-inlineadmin-and-a-post-save-signal-in-djan – Nikita Nov 26 '13 at 11:26
  • 1
    Thanks Nikita, this looks pretty much exactly like my problem. Unfortunately my previous searches didn't return this question. The answer looks like the ideal solution to resolve my issue. – chewynougat Nov 26 '13 at 12:22
  • Although the above link solved the unique constraint issue, I have an M2M field in the UserProfile and as I already have a live set of users, updating the OneToOneField to be the primary key and performing a (South) migration leads to the data in the intermediate M2M table becoming invalid. Rather than having to go through the painstaking process of ensuring this M2M table is updated correctly to point to the correct UserProfile (user_)id for each row I have found the following answer (to a different question) to be a better solution to my problem: http://stackoverflow.com/a/10342823/1328695 – chewynougat Nov 26 '13 at 15:05
  • http://stackoverflow.com/questions/14345303/creating-a-profile-model-with-both-an-inlineadmin-and-a-post-save-signal-in-djan – Dmitry Yudin Jun 16 '15 at 12:00

0 Answers0