Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Query ManyToMany with Custom Through Table Field Data

I've been trying to figure this one out for a while now but am confused. Every ManyToMany relationship always goes through a third table which isn't that difficult to understand. But in the event that the third table is a custom through table with additional fields how do you grab the custom field for each row?

Here's a sample table I made. How can I get all the movies a User has watched along with the additional watched field and finished field? This example assumes the user is only allowed to see the movie once whether they finish it or not so there will only be 1 record for each movie they saw.

class Movie(models.Model):
    title = models.CharField(max_length=191)

class User(models.Model):
    username = models.CharField(max_length=191)
    watched = models.ManyToMany(Movie, through='watch')

class Watch(models.Model):
    user = models.Foreignkey(User, on_delete=models.CASCADE)
    movie = models.Foreignkey(Movie, on_delete=models.CASCADE)
    watched = models.DateTimeField()
    finished = models.BooleanField()

Penny for your thoughts my friends.

like image 903
enchance Avatar asked Oct 18 '25 03:10

enchance


1 Answers

You can uses:

from django.db.models import F

my_user.watched.annotate(
    watched=F('watch__watched'),
    finished=F('watch__finished')
)

This will return a QuerySet of Movies that contain as extra attributes .watched and .finished.

That being said, it might be cleaner to just access the watch_set, and thus iterate over the Watch objects and access the .movie object for details about the movie. You can use .select_related(..) [Django-doc] to fetch the information about the Movies in the same database query:

for watch in my_user.watch_set.select_related('movie'):
    print(f'{watch.movie.title}: {watch.watched}, {watch.finished}')
like image 161
Willem Van Onsem Avatar answered Oct 20 '25 18:10

Willem Van Onsem