I created a 'profile' model (with a 1-to-1 relationship to the User model) as described on Extending the existing user model. The profile model has an optional many-to-one relationship to another model:
class Profile(models.Model):
user = models.OneToOneField(User, primary_key=True)
account = models.ForeignKey(Account, blank=True, null=True, on_delete=models.SET_NULL)
As documented there, I also created an inline admin:
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'profiles'
# UserAdmin and unregister()/register() calls omitted, they are straight copies from the Django docs
Now if I don't select an account
in the admin when creating the user, the profile model won't be created. So I connect to the post_save signal, again just following the documentation:
@receiver(post_save, sender=User)
def create_profile_for_new_user(sender, created, instance, **kwargs):
if created:
profile = Profile(user=instance)
profile.save()
This works fine as long as I do not select an account
in the admin, but if I do, I'll get an IntegrityError
exception, telling me that duplicate key value violates unique constraint "app_profile_user_id_key" DETAIL: Key (user_id)=(15) already exists.
Apparently, the inline admin tries to creates the profile
instance itself, but my post_save
signal handler has already created it at that time.
How do I fix this problem, while keeping all of the following requirements?
- No matter how the new user is created, there will always be a
profile
model linking to it as well afterwards. - If the user selects an
account
in the admin during user creation, thisaccount
will be set on the newprofile
model afterwards. If not, the field isnull.
Environment: Django 1.5, Python 2.7
Related questions:
- Creating a extended user profile (similar symptoms, but the cause turned out to be a different one)