问题
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.
来源:https://stackoverflow.com/questions/20214362/post-save-user-signal-that-creates-user-profile-is-being-called-twice-causing-du