Reputation: 51
I have an ExtendedUser
model like this, that just points to Django's User
model:
class ExtendedUser(models.Model):
user = models.OneToOneField(User)
When a request comes in, I want to get or create an User
and its related ExtendedUser
if the user that I'm looking for doesn't exist. I have this code :
def get_or_create_user(username):
with transaction.atomic():
user, created = User.objects.get_or_create(
username=username,
defaults={
'first_name': "BLABLA",
},
)
if created:
extended_user = ExtendedUser()
extended_user.user = user
extended_user.save()
return user
I wrap it inside a transaction, to be sure I don't create an User
but not its associated ExtendedUser
.
But, when two requests come in simultaneously that will create the same user, this fails from time to time with an IntegrityError
, for both requests. So I end up with no user being created..
IntegrityError: (1062, "Duplicate entry 'BLABLABLA' for key 'username'")
Note that I use MySQL, but I force READ COMMITTED
isolation level.
What do I do wrong ? How should I handle this ? The models need to stay as they are.
Upvotes: 1
Views: 1198
Reputation: 3286
Maybe you should solve this problem using signals.
After a User is saved, a signal will be fired. It is in the signal handler where you should create your ExtendedUser.
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
ExtendedUser.objects.create(user=instance)
Upvotes: 1