在模型管理员中访问父模型实例以提供自定义查询集

时间:2019-08-05 13:41:53

标签: django model django-admin

我想在继承自TabluarInline的模型管理类中提供自定义查询集,但我想通过调用模型对象当前实例的方法来提供此查询集。

我有两个模型。一个用于属于专辑的曲目,另一个用于专辑本身。一些曲目可以隐藏,我在Album中有一个方法仅返回可见曲目。

class Track(models.Model):
    name = models.CharField()
    length = models.IntegerField()
    album = ForeignKey(Album)
    hidden = BooleanField()

class Album(models.Model):
    name = models.CharField()

    def get_visible_tracks_queryset(self):    
        return self.track_set.filter(hidden=False)

我有一个曲目内联管理员,该专辑包含在django管理员页面中。我想重新使用get_visible_tracks_queryset来为此内联管理员定义queryset,我不想再次重复该逻辑。我不知道该怎么做。我可以做类似以下的事情,但是我在这里使用了一个简化的示例,实际上我有更复杂的逻辑,并且我不想在多个地方重复该逻辑。

class TracksInlineAdmin(admin.TabularInline):
    fields = ("name", "length")
    model = Track

    def get_queryset(self, request):
        qs = super(TracksInlineAdmin, self).get_queryset(request)
        return qs.filter(hidden=False)

理想情况下,我可以执行以下操作:

class TracksInlineAdmin(admin.TabularInline):
    fields = ("name", "length")
    model = Track

    def get_queryset(self, request, parent_model_instance):
        return parent_model_instance.get_visible_tracks_queryset()

关于如何实现这一目标的任何想法?

1 个答案:

答案 0 :(得分:1)

最干净的方法是为模型定义一个自定义QuerySet类,您可以在其中定义任何复杂的过滤器以在各个地方重复使用:

class Track(models.Model):
    # fields defined here

    objects = TrackManager()


class TrackManager(models.Manager):

    def get_queryset(self):
        return TrackQuerySet(self.model, using=self._db)


class TrackQuerySet(models.QuerySet):

    def visible(self):
        return self.filter(hidden=False)

现在,在代码中的任何位置,当您有一个查询集(例如Track.objects.filter(name="my movie"))时,都可以添加.visible()进行进一步过滤。也在相关集上:

album.track_set.all().visible()