get_or_create throws Integrity Error

Question:

Given that the whole point of object.get_or_create() is to get the object if it already exists, I fail to see why it’s throwing an integrity error for this code:

class UserAdd(TemplateView):

def post(self, request, *args, **kwargs):
    context = self.get_context_data(*args, **kwargs)
    form = UserAddForm(request.POST)
    if form.is_valid():
        first_name = form.cleaned_data['first_name']
        last_name = form.cleaned_data['last_name']
        myemail = form.cleaned_data['email']
        mypass = form.cleaned_data['password']
        if myemail and mypass:
            myuser,created = User.objects.get_or_create(email=myemail, username=myemail, first_name=first_name, last_name=last_name)
            if created:
                myuser.set_password(mypass)
    return HttpResponseRedirect('/')

Here is the error:

django.db.utils.IntegrityError IntegrityError: (1062, "Duplicate entry '[email protected]' for key 'username_UNIQUE'")

Anyone know what’s going on?

Asked By: Foo Party

||

Answers:

You are asking django to fetch a record based on four conditions:

  • email
  • username
  • first_name
  • last_name

So all four fields combined does not have a record.

You should do:

myuser, created = User.objects.get_or_create(
   username=myemail, defaults={'first_name': first_name, 'last_name': last_name, 'email': myemail})
Answered By: Aamir Rind

The parameters sent into the get_or_create method need to match exactly, or django’s ORM would try to create a new object, and since a primary key/unique column constraint would be violated, you are getting the error.

Try this:

if form.is_valid():
    first_name = form.cleaned_data['first_name']
    last_name = form.cleaned_data['last_name']
    myemail = form.cleaned_data['email']
    mypass = form.cleaned_data['password']
    if myemail and mypass:
        myuser,created = User.objects.get_or_create(email=myemail, defaults = {'username': myemail, 'first_name': first_name, 'last_name': last_name})
        if created:
            myuser.set_password(mypass)

return HttpResponseRedirect('/')

Read more on get_or_create here. The defaults= argument is what you needed.

Answered By: karthikr

I have faced similar error after redefining model’s save() method. It turns out that in case you call save more than once inside your model, all consequent calls should be made with force_insert=True keyword argument. In my case I had to change self.save(*args, **kwargs) to self.save() on second call to get rid of the error.
For more details read here: https://code.djangoproject.com/ticket/28253

Answered By: Vadym Pasko
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.