Paris
Paris

Reputation: 6771

Django combine foreign keys in a single queryset

I have a model in a Django application that is being referenced by multiple other models as a ForeignKey.

What I am looking for is for a way to create a single queryset for all objects of this class that are being referenced as ForeignKey by the rest of the classes based on some criteria.

I am not even sure if this is possible, but I thought about asking anyway.

class Person(models.Model):
    pass


class Book(models.Model):
    year_published = models.PositiveIntegerField()
    author = models.ForeignKey(Person)


class MusicAlbum(models.Model):
    year_published = models.PositiveIntegerField()
    producer = models.ForeignKey(Person)

recent_books = Book.objects.filter(year_published__gte=2018)
recent_music_albums = MusicAlbum.objects.filter(year_published__gte=2018)

# How can I create a **single** queryset of the Person objects that are being referenced as `author` in `recent_books` and as `producer` in `recent_music_albums`?

Thanks for your time.

Upvotes: 1

Views: 1403

Answers (3)

pradip yadav
pradip yadav

Reputation: 143

Same can be achieved by this :

person = Person.objects.latest('book__year_published', 'musicalbum__year_published')

or

personList = Person.objects.all().order_by('-book__year_published', '-musicalbum__year_published')

Upvotes: 0

wim
wim

Reputation: 363043

You will have on Person model instances a RelatedManager for Books and MusicAlbums. Probably they will still have the default names book_set and musicalbum_set since you didn't override them.

You can use these to find the books/music albums associated with one person instance:

persons_books = person.book_set.all()
persons_musicalbums = person.musicalbum_set.all()

And similarly you can generate the relevant queryset from the model manager:

qs = Person.objects.exclude(book=None).exclude(musicalbum=None)

Upvotes: 1

scnerd
scnerd

Reputation: 6103

I don't have Django in front of me at the moment, but what about something like:

class Person(models.Model):
    pass


class Book(models.Model):
    year_published = models.PositiveIntegerField()
    author = models.ForeignKey(Person, related_name='books')


class MusicAlbum(models.Model):
    year_published = models.PositiveIntegerField()
    producer = models.ForeignKey(Person, related_name='albums')

Person.objects.filter(books__year_published__gte=2018, albums__year_published__gte=2018)

Or, if you have to do those first two queries anyway,

Person.objects.filter(books__in=recent_books, albums__in=recent_music_albums)

Upvotes: 2

Related Questions