6

can you help me understand why this code causes a duplicate entry (IntegrityError)?

I'm on Django 1.2.

(row, is_new) = MyModel.objects.get_or_create(field1=1)
row.other_field = 2
row.save()

I do have a unique constraint on field1. If there is a row where field1=1, everything works fine, Django does a "get".

If there is not a row where field1=1, it looks like Django is creating that row which is ok. But why won't it let me save it?

Update:

If it helps, here is MyModel:

class MyModel(models.Model):
    id = models.BigIntegerField(primary_key=True)
    field1 = models.BigIntegerField(unique=True)
    other_field = models.CharField(max_length=765)
    class Meta:
        db_table = u'project_crosses_suppl_FO'

field1 is a foreign key to another table. But I didn't make a model in Django for that table so I don't tell Django it's a foreign key.

Greg
  • 45,306
  • 89
  • 231
  • 297
  • Does MyModel have foreign field? Can you post code of MyModel? – przemo_li Aug 17 '11 at 18:18
  • 1
    [This similar question](http://stackoverflow.com/questions/6974463/django-get-or-create-raises-duplicate-entry-with-together-unique) might help you. – agf Aug 17 '11 at 18:31
  • @agf. I don't understand what the resolution was in that question, or how the problem is justified. It sounds like a bug to me. I think I'll give up on get_or_create and do a work around :-( – Greg Aug 17 '11 at 18:43
  • can you set a charfield to an integer? does that work? – andrew cooke Aug 17 '11 at 20:17

3 Answers3

7

Assuming that's a reasonably faithful representation of your real code, not surprisingly it's not Django that's busted, it's your model.

You've overridden the automatic primary key field with your own id field, but neglected to make it an autoincrement. So the database is not using a new value for the PK, hence the integrity error.

Unless you have a really good reason, you should let Django deal with the PK field itself.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • 1
    Oh that's a good point. It's an existing table that I can't change. That's why I'm telling Django what the primary key is. So what do I change exactly? The column "id" in the MySQL table is actually set to auto-increment. Do I need to tell Django it's an auto-increment field? – Greg Aug 18 '11 at 12:07
3

get_or_create sounds busted to me. I'm just doing this work around:

rows = MyModel.objects.filter(field1=1)
row = rows[0] if rows else MyModel(field1=1)
row.other_field = 2
row.save()
Greg
  • 45,306
  • 89
  • 231
  • 297
2

Get or Create returns a tuple of results even if your field you use is set as primary key or unique.

So in your case: row is a tuple with one object, hence this should work for you:

(row, is_new) = MyModel.objects.get_or_create(field1=1)
row[0].other_field = 2
row[0].save()