Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use two unique constraints in Django model?

I have a Django model for a player of a game

class Player(models.Model):
    name = models.CharField(max_length=50)
    team = models.ForeignKey('Team', on_delete=models.CASCADE, blank=True, null=True)
    game = models.ForeignKey('Game', on_delete=models.CASCADE)
    objects = GameManager()

    class Meta:
       unique_together = ('name', 'game',)

I have only one unique constraint, that the name and the game are unique together.

Now, I would like to extend our page by adding registered users. So, I would add this to the model.

        user = models.ForeignKey('auth.User', on_delete=models.CASCADE, blank=True, null=True)

So, an registered user can subscribe to a game by adding a name, team, game, and his/her user. However, the user should only be able to add his account once to an game, which would be a second unique constrain

       unique_together = ('user', 'game',)

Is it possible to give in Django two unique constraints to the model? Or do I have to search in the table manually prior to saving the new entries? Or is there a better way?

like image 953
Cometchaser Avatar asked Jan 05 '19 21:01

Cometchaser


People also ask

How do you make two fields unique in Django?

To make fields unique together, we create a class Meta. In this class, we specify the keyword, unique_together, and then create a tuple consisting of all the fields that we want unique together. In this case, we just want 2 fields unique together, but you can specify as many as you want, as long as it's 2 or greater.

How can we make unique field in Django model?

Of course, you should have an id tag, which is always unique, because it's a primary key. However, certain fields may also need to be unique, because certain fields may need to be unique without any repetition. So, to make a field unique in Django is very basic. You just set the unique attribute to true.

What is unique together in Django?

unique_together may be deprecated in the future. This is a list of lists that must be unique when considered together. It's used in the Django admin and is enforced at the database level (i.e., the appropriate UNIQUE statements are included in the CREATE TABLE statement).

How do I create a one to many relationship in Django?

To handle One-To-Many relationships in Django you need to use ForeignKey . The current structure in your example allows each Dude to have one number, and each number to belong to multiple Dudes (same with Business).


2 Answers

Yes, in fact by default unique_together is a collection of collections of fields that are unique together, so something like:

class Player(models.Model):
    name = models.CharField(max_length=50)
    team = models.ForeignKey('Team', on_delete=models.CASCADE, blank=True, null=True)
    game = models.ForeignKey('Game', on_delete=models.CASCADE)
    objects = GameManager()

    class Meta:
       unique_together = (('name', 'game',), ('user', 'game',))

Here we thus specify that every name, game pair is unique, and every user, game pair is unique. So it is impossible to create two Player objects for the same user and game, or for the same game and name.

It is only because a single unique_together constraint is quite common, that one can also pass a single collection of field names that should be unique together, as is written in the documentation on Options.unique_together [Django-doc]:

Sets of field names that, taken together, must be unique:

unique_together = (("driver", "restaurant"),)

This is a tuple of tuples that must be unique when considered together. It's used in the Django admin and is enforced at the database level (i.e., the appropriate UNIQUE statements are included in the CREATE TABLE statement).

For convenience, unique_together can be a single tuple when dealing with a single set of fields:

unique_together = ("driver", "restaurant")
like image 166
Willem Van Onsem Avatar answered Oct 26 '22 06:10

Willem Van Onsem


You should use models.UniqueConstraint (reference).

As noted in the reference:

UniqueConstraint provides more functionality than unique_together. unique_together may be deprecated in the future.

Do this:

class Meta:
    constraints = [
        models.UniqueConstraint(fields=['name', 'game'], name="unique_name_game"),
        models.UniqueConstraint(fields=['user', 'game'], name="unique_user_game"),
 ]
like image 38
Seyed Mostafa SeyedAshoor Avatar answered Oct 26 '22 05:10

Seyed Mostafa SeyedAshoor