Luke
Luke

Reputation: 109

Django get_or_create() is creating multiple rows with the same id

I have a get_or_create() in my django app that's creating duplicate rows and assigning them the same id.

stock_search, created = SearchRequest.objects.get_or_create(quote=quote, salesperson=user)

count() doesn't count these rows more than once but any queries I run on the data returns the duplicated rows.

Any ideas what could be causing this to happen?

Model Definition

class SearchRequest(models.Model):
    salesperson             =   models.ForeignKey(User, blank=True, null=True, related_name='sales')
    purchaser               =   models.ManyToManyField(User, blank=True, null=True, related_name='purchaser')
    datesent                =   models.DateTimeField(auto_now_add=False, verbose_name=("Date Sent"), blank=True, null=True)
    notes                   =   models.TextField(default='', blank=True, null=True)
    full_search             =   models.BooleanField(verbose_name=("Full Search"), blank=True, default=False)
    quote                   =   models.ForeignKey('Quote.Quote', blank=True, null=True)
    lead_time               =   models.ForeignKey('Logistics.LeadTime', blank=True, null=True)
    call_list               =   models.BooleanField(verbose_name=("Call List"), blank=True, default=False)
    email_list              =   models.BooleanField(verbose_name=("Email List"), blank=True, default=False)
    accepted                =   models.ForeignKey(User, blank=True, null=True, related_name='search_accepted')
    dateaccepted            =   models.DateTimeField(auto_now_add=False, verbose_name=("Date Accepted"), blank=True, null=True)

Cheers

Upvotes: 0

Views: 4214

Answers (1)

e4c5
e4c5

Reputation: 53774

As mentioned in the docs, you need an unique index for get_or_create to work

This method is atomic assuming correct usage, correct database configuration, and correct behavior of the underlying database. However, if uniqueness is not enforced at the database level for the kwargs used in a get_or_create call (see unique or unique_together), this method is prone to a race-condition which can result in multiple rows with the same parameters being inserted simultaneously.

So you class needs

class SearchRequest(models.Model):
    class Meta:
        unique_together('quote','salesperson')

which should be placed after the field definitions.

Upvotes: 4

Related Questions