4

Help! Can't figure this out! I'm getting a Integrity error on get_or_create even with a defaults parameter set.

Here's how the model looks stripped down.

class Example(models.Model):model
    user            = models.ForeignKey(User)
    text            = models.TextField()

def __unicode__(self):
    return "Example"

I run this in Django:

def create_example_model(user, textJson):
    defaults = {text: textJson.get("text", "undefined")}

    model, created = models.Example.objects.get_or_create(
            user=user, 
            id=textJson.get("id", None), 
            defaults=defaults)

    if not created:
        model.text = textJson.get("text", "undefined")
        model.save()

    return model

I'm getting an error on the get_or_create line:

IntegrityError: (1062, "Duplicate entry '3020' for key 'PRIMARY'")

It's live so I can't really tell what the input is.

Help? There's actually a defaults set, so it's not like, this problem where they do not have a defaults. Plus it doesn't have together-unique. Django : get_or_create Raises duplicate entry with together_unique

I'm using python 2.6, and mysql.

Community
  • 1
  • 1
Kenneth
  • 611
  • 2
  • 8
  • 17

3 Answers3

2

You shouldn't be setting the id for objects in general, you have to be careful when doing that.

Have you checked to see the value for 'id' that you are putting into the database?

If that doesn't fix your issue then it may be a database issue, for PostgreSQL there is a special sequence used to increment the ID's and sometimes this does not get incremented. Something like the following:

SELECT setval('tablename_id_seq', (SELECT MAX(id) + 1 FROM tablename_id_seq));

Dominic Santos
  • 1,900
  • 12
  • 14
  • id is set only if it already exists. If the id is null, it will be auto generated from the database (auto increment). At least that's what I understood. – Kenneth Sep 14 '11 at 17:51
2

get_or_create() will try to create a new object if it can't find one that is an exact match to the arguments you pass in.

So is what I'm assuming is happening is that a different user has made an object with the id of 3020. Since there is no object with the user/id combo you're requesting, it tries to make a new object with that combo, but fails because a different user has already created an item with the id of 3020.

Hopefully that makes sense. See what the following returns. Might give a little insight as to what has gone on.

models.Example.objects.get(id=3020)

You might need to make 3020 a string in the lookup. I'm assuming a string is coming back from your textJson.get() method.

Alex Jillard
  • 2,792
  • 2
  • 19
  • 20
  • The object exists under one user. Could it be possible that concurrent requests are going in? – Kenneth Sep 14 '11 at 17:49
  • If that object already exists, it's going to try and create ANOTHER object (with a different user), but you're assigning the ID, which must be unique. That's why you're getting the error. Shouldn't have anything to do with concurrent requests. – Alex Jillard Sep 15 '11 at 17:28
0

One common but little documented cause for get_or_create() fails is corrupted database indexes.

Django depends on the assumption that there is only one record for given identifier, and this is in turn enforced using UNIQUE index on this particular field in the database. But indexes are constantly being rewritten and they may get corrupted e.g. when the database crashes unexpectedly. In such case the index may no longer return information about an existing record, another record with the same field is added, and as result you'll be hitting the IntegrityError each time you try to get or create this particular record.

The solution is, at least in PostgreSQL, to REINDEX this particular index, but you first need to get rid of the duplicate rows programmatically.

kravietz
  • 10,667
  • 2
  • 35
  • 27