Zaraki Kenpachi
Zaraki Kenpachi

Reputation: 5740

Django ForeignKey reverse Query

I have 3 models related witch each other with FK:

class MainEvent(models.Model):
    name = models.CharField(max_length=512, blank=True)

class Event(models.Model):
    main_event = models.ForeignKey(MainEvent, blank=True, null=True, on_delete=models.CASCADE)
    name = models.CharField(max_length=512, blank=True)

class SubEvent(models.Model):
    event = models.ForeignKey(Event, blank=True, null=True, on_delete=models.CASCADE)
    done = models.BooleanField(default=False)

What i need is to create single reverse query on model MainEvent that holds related Events and Subevents. I will use this with Q for filter multiple options.

For example:

there are 2 MainEvents, each of them have 2 or more Events and each Event have 2 or more Subevents. I'm trying to create single Query something like this:

 [MainEvent_1:[Event_1:[Subevent_1,Subevent_2,...],Event_2:[Subevent_5,...]], MainEvent_2:[Event_2:[Subevent_2,..]]]

For now I'm creating dictionary that holds desired output, but with this i con't use Q relations like & or |.

At the end i'm using this data in template table to show all events and filter them:

desired table structure:

main event_1:
event_1:
subevent_1
subevent_2
event_2:
subev...
...........
main event_2:
event_2:
subev....

Thank you for your time.

Upvotes: 0

Views: 104

Answers (2)

Exprator
Exprator

Reputation: 27523

MainEvent.objects.filter(Q(event__subevent__done=True) | Q(event__subevent__done=False))

you can use something like this and then access the sub events using . inside loop

for item in query:
    for i in item.event_set.all():
        for j in i.subevent_set.all():
            print(i.name)
            print(j.done)

Upvotes: 1

Daniel Hepper
Daniel Hepper

Reputation: 29957

You cannot do it in one query, but you can do it in three queries using prefetch_related():

MainEvent.objects.prefetch_related('event_set', 'event_set__subevent_set').all()

If all of your MainEvents have Events and all of your Events have SubEvents, you could do it in one query by starting from SubEvents and doing the grouping in code:

SubEvent.objects.select_related('event', 'event__main_event').all()

Upvotes: 0

Related Questions