反向查找基于外键查询集数据

时间:2015-01-03 23:48:23

标签: django django-models django-queryset

好的,我相信标题可能令人困惑。随着我们的进展,我可能会更新问题标题,以便更好地反映它所指的内容。

然而。我目前有3个模型,ZoneBossDifficulty。模型通过ForeignKey关系链接,如:

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"

我想要实现的目标是根据Zone过滤每个Difficulty

例如

如果第1区的Boss有3个不同的困难[a, b, c],我希望能够获取数据,以便我可以在模板区域1(难度A),区域1中单独显示(难度B)和1区(难度C)并相应地列出每个区域的老板。

1 个答案:

答案 0 :(得分:1)

如果您将ManyToManyField添加到Zone(或Difficulty),这会更容易一些:

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

然后,您可以查询与单个区域相关的所有困难:

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

要提高效果,请使用prefetch_related('difficulties')。在Django 1.7中,你可以使用新的Prefetch object来预取老板:

# 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(...)