Saadat Ali
Saadat Ali

Reputation: 37

unique_together not working as expected in view

I added unique_together in the Django model. It works fine in the Django admin panel but doesn't work when I create model instances in a for loop in the Django view.

My Model:

class Parent(models.Model):
    attribute_1 = models.CharField(max_length=100)
    attribute_2 = models.IntegerField()
    attribute_3 = models.CharField(max_length=100)

    class Meta:
        unique_together = (("attribute_1", "attribute_2"),)

View:


class ParentView(View):
    template_name = "app/index.html"

    def get(self, *args, **kwargs):

        for i in range(10):
            Parent.objects.create(
                attribute_1=f"value-{i}",
                attribute_2=i,
                attribute_3=f"value-{i}",
            )
        return render(self.request, self.template_name)

Problem:

When I open this view, it creates the entries in the Parent model. when I refresh the page, I expect a unique value error but it doesn't give any error at all and creates entries again. No matter how much time I reload the page, it creates duplicate entries without giving an error.

What I tried?

  1. I tried to change my DB from sqlite3 to PostgreSQL but it didn't work.
  2. I tried to switch attributes but no luck.
  3. It works perfectly fine on the admin panel.

Upvotes: 1

Views: 154

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476547

It works perfectly fine on the admin panel.

That is because it is validated by a ModelForm, you can check this before saving with .full_clean(…) [Django-doc]:

class ParentView(View):
    template_name = 'app/index.html'

    def get(self, *args, **kwargs):
        for i in range(10):
            parent = Parent(
                attribute_1=f'value-{i}',
                attribute_2=i,
                attribute_3=f'value-{i}',
            )
            parent.full_clean()
            parent.save()
        return render(self.request, self.template_name)

Most databases can enforce unique constraints, you will have to makemigrations and migrate.


Note: As the documentation on unique_together [Django-doc] says, the unique_together constraint will likely become deprecated. The documentation advises to use the UniqueConstraint [Django-doc] from Django's constraint framework.

Upvotes: 1

Related Questions