mashedpotatoes
mashedpotatoes

Reputation: 47

Django unique_together on primary key

Currently I have three models:

class Tutorial(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField()
    videos = models.ManyToManyField('TutorialVideo', through='TutorialVideoThrough', blank=True)


class TutorialVideo(models.Model):
    name = models.CharField(max_length=100)
    video = S3DirectField(dest='tutorial_vids')
    length = models.CharField("Length (hh:mm:ss)",max_length=100)
    tutorials = models.ManyToManyField(Tutorial, through='TutorialVideoThrough', blank=True)


class TutorialVideoThrough(models.Model):
    tutorial = models.ForeignKey(Tutorial, related_name='tutorial_video_through', blank=True, null=True)
    video = models.ForeignKey(TutorialVideo, related_name='video_tutorial_through', blank=True, null=True)
    order = models.IntegerField()

A Tutorial can have many TutorialVideos through TutorialVideoThrough. On the TutorialVideoThrough, I have an order field to decide what order to show the videos in. Is there a way to validate that there are no duplicate order integers? For example, if I am linking two TutorialVideos to a Tutorial through TutorialVideoThrough, and I put the first one as order 1, then I shouldn't be able to give the second video as order 1.

I tried using unique_together = ('id', 'order') on TutorialVideoThrough, but it didn't work.

Upvotes: 3

Views: 1583

Answers (2)

Alasdair
Alasdair

Reputation: 309099

If you want each order to be unique for each tutorial, then you want

unique_together = (
    ('tutorial', 'order'),
)

You probably want each video to appear only once in each tutorial. If that's the case, add ('tutorial', 'video') to unique_together.

unique_together = (
    ('tutorial', 'order'),
    ('tutorial', 'video'),
)

Note that you should only define the many to many relation on one side of the model. If you have

class Tutorial(models.Model):
    videos = models.ManyToManyField('TutorialVideo', through='TutorialVideoThrough', blank=True, related_name='tutorials')

then you should remove the tutorial field from the TutorialVideo model.

Upvotes: 2

GwynBleidD
GwynBleidD

Reputation: 20569

primary_key is always unique, so your unique_together pair also will be always unique.

If you must ensure that there are no videos with same order, you must first answer question: regarding to what?

If you want to have your uniqueness in list of TutorialVideos in Tutorials, your unique_together should be:

unique_together = (('tutorial', 'order'),)

If you want uniqueness in list of Tutorials in TutorialVideos, your unique_together should be:

unique_together = (('video', 'order'),)

But setting order as unique is not good idea, you will have some issues when trying to reorder your fields.

Upvotes: 4

Related Questions