Django unique_together not preventing duplicates

Question:

I am clearly not understanding how to do this correctly, can someone set me straight. Here is the model:

class Team(models.Model):
   teamID=models.CharField(max_length=255) #this will be generated on the iPad
   name=models.CharField(max_length=255)
   slug=models.SlugField(max_length=50) 
   teamNumber=models.CharField(max_length=30)
   checkIn=models.DateTimeField(default=datetime.now())
   totalScore=models.IntegerField(max_length=6) 

   class Meta:
       unique_together = ("teamID", "name", "slug", "teamNumber", "totalScore")

If I submit twice in a row it saves all of it. Yikes!!!

Asked By: jasongonzales

||

Answers:

Try the proper nested-tuple syntax ((foo,bar),) instead of just (foo, bar)?

https://docs.djangoproject.com/en/dev/ref/models/options/#unique-together

Answered By: Steve Jalim

Yes the paremeter unique_together receives as input a tuple of tuples, I have not tested tuples of more than two elements but it should work

for your example:

unique_together = (("teamID", "name"), ("slug", "teamNumber"))

or:

unique_together = (("teamID", "name", "slug", "teamNumber", "totalScore"))
Answered By: Andres

As aganders3 mentions the constraint is enforced at the database level; I assume though that you are using a database like SQLite that doesn’t support this kind of constraint.

The reason that it all works as expected through the admin is that it is doing the uniqueness check itself (it doesn’t rely strictly on the database to signal constraint violations).

You can switch to a database engine that supports this kind of uniqueness constraint (either MySQL or Postgres would work) or you could look at adding the check in using signals: http://djangosnippets.org/snippets/1628/

Answered By: Stefan Magnuson

I found this approach helpful without adding any unnecessary fields

class Request(models.Model):
    user = models.ForeignKey(User, related_name='request_list', on_delete=models.CASCADE)
    requested_user = models.ForeignKey(User, on_delete=models.CASCADE)
    request_date = models.DateField(default=timezone.now())
    request_status = models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        # Checking for duplicate requests
        try:
            request = Request.objects.get(user=self.user, requested_user=self.requested_user)
            raise ValidationError('Duplicate Value', code='invalid')
        except self.DoesNotExist:
            super().save(*args, **kwargs)

        # Checking for reversed duplicate requests
        try:
            request_new = Request.objects.get(requested_user=self.user, user=self.requested_user)
            raise ValidationError('Duplicate Value', code='invalid')
        except self.DoesNotExist:
            super().save(*args, **kwargs)

    def __str__(self):
        return self.user.username + '------>' + self.requested_user.username
Answered By: Saurav Biswas
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.