Llanilek
Llanilek

Reputation: 3466

reverse look up based on foreign key queryset data

Ok, I trust that the title may be confusing. As we go along I may update the question title in order to better reflect what it is referring to.

However. I have 3 models currently, Zone, Boss and Difficulty. The models are linked via ForeignKey relationships like so:

class Difficulty(models.Model):
    '''Define the difficulties available in game'''
    difficulty = models.CharField(max_length=255, null=True)

    def __unicode__(self):
        return self.difficulty

    class Meta:
        verbose_name = "Difficulty Setting"
        verbose_name_plural = "Difficulties"


class Zone(models.Model):
    '''Stores the Zone information, referred to in-game as a Raid Instance'''
    name = models.CharField(max_length=255, null=True)
    zone_id = models.IntegerField(null=True)

    def __unicode__(self):
        return self.name


class Boss(models.Model):
    '''Stores the information for each boss encounter within each zone'''
    name = models.CharField(max_length=255, null=True)
    boss_id = models.IntegerField(null=True, blank=True)
    zone = models.ForeignKey(Zone, null=True)
    difficulty = models.ForeignKey(Difficulty, null=True)
    guild_defeated = models.BooleanField(default=False)
    appearance = models.IntegerField(null=True, blank=True)

    def __unicode__(self):
        return u'%s [%s]' % (self.name, self.difficulty)

    class Meta:
        ordering = ['difficulty', 'appearance']
        verbose_name = "Boss"
        verbose_name_plural = "Bosses"

What I am trying to achieve, Is filter each Zone, based on Difficulty.

For example

If Zone 1 has a Boss with 3 separate difficulties [a, b, c] I want to be able to get the data so that I can separately show in the template Zone 1 (Difficulty A), Zone 1 (Difficulty B) and Zone 1 (Difficulty C) and list each of the zones' bosses accordingly.

Upvotes: 0

Views: 117

Answers (1)

knbk
knbk

Reputation: 53719

This is a bit easier if you add a ManyToManyField to Zone (or Difficulty):

class Zone(models.Model):
    difficulties = models.ManyToManyField(Difficulty, through=Boss, related_name='zones')

Then, you can query for all the difficulties related to a single zone:

for difficulty in zone.difficulties.all():
    bosses = difficulty.boss_set.filter(zone=zone)

To help with performance, use prefetch_related('difficulties'). In Django 1.7 you can use the new Prefetch object to also prefetch the bosses:

# I think that's how the new `Prefetch` works, I haven't actually used it yet.
zone = Zone.objects.prefetch_related(
           Prefetch('difficulties'),
           Prefetch('difficulties__bosses', queryset=Boss.objects.filter(zone_id=zone_id),
       ).get(...)

Upvotes: 1

Related Questions