Reputation: 47164
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.
Upvotes: 6
Views: 6475
Reputation: 21
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()
Upvotes: 2
Reputation: 600041
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.
Upvotes: 7
Reputation: 47164
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()
Upvotes: 3