12

我的模型设置如下:

class ParentModel(models.Model):
    some_col = models.IntegerField()
    some_other = models.CharField()

class ChildModel(models.Model)
    parent = models.ForeignKey(ParentModel, related_name='children')

class ToyModel(models.Model)
    child_owner = models.ForeignKey(ChildModel, related_name='toys')

现在在我的管理面板中,当我打开更改列表时,ParentModel我希望 list_display 中有一个新字段/列,其中包含一个链接以打开更改列表,ChildModel但应用过滤器仅显示来自所选父级的子级。现在我用这种方法实现了它,但我认为有一种更清洁的方法可以做到这一点,我只是不知道如何:

class ParentAdmin(admin.ModelAdmin)
    list_display = ('id', 'some_col', 'some_other', 'list_children')
    def list_children(self, obj):
        url = urlresolvers.reverse('admin:appname_childmodel_changelist')
        return '<a href="{0}?parent__id__exact={1}">List children</a>'.format(url, obj.id)
    list_children.allow_tags = True
    list_children.short_description = 'Children'        

admin.site.register(Parent, ParentAdmin)

所以我的问题是,如果没有这种“链接黑客”,是否有可能实现同样的目标?ParentModel如果它的任何孩子有玩具,是否可以在更改列表的单独列中指出?

4

1 回答 1

4

我认为您显示该list_children列的方法是正确的。不要担心“链接黑客”,这很好。

要显示一列以指示对象的任何孩子是否有玩具,只需在ParentAdmin类上定义另一个方法,然后list_display像以前一样将其添加到。

class ParentAdmin(admin.ModelAdmin):
    list_display = ('id', 'some_col', 'some_other', 'list_children', 'children_has_toys')
    ...
    def children_has_toys(self, obj):
        """
        Returns 'yes' if any of the object's children has toys, otherwise 'no'
        """
        return ToyModel.objects.filter(child_owner__parent=obj).exists()
    children_has_toys.boolean = True

设置boolean=True意味着 Django 将呈现“开”或“关”图标,就像它为布尔字段所做的那样。请注意,这种方法需要每个父项进行一次查询(即 O(n))。您必须进行测试以查看您是否在生产中获得了可接受的性能。

于 2011-12-18T11:36:54.390 回答