在Django admin中内联显示子级

时间:2019-01-03 15:54:05

标签: python django

在Django 1.11中,我有2个模型,FooBar

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

class Bar(models.Model):
    name = models.CharField()
    foo = models.ForeignKey(Foo)

当我在Django管理员中访问Foo页面时,我希望能够看到其下方的Bar列表。所以我在admin.py中这样做:

class BarInline(admin.StackedInline):
    model = Bar

@admin.register(Foo)
class FooAdmin(admin.ModelAdmin):
    list_display = ('name')
    fields = ('name')
    inlines = [BarInline]

但是,我真正想要的是可单击链接的列表,这些链接指向一个单独的页面,我可以在其中编辑每个Bar(以及“添加”按钮以向此Foo添加新Bar)。即我不需要整个内联表单。在Django中怎么可能?

2 个答案:

答案 0 :(得分:2)

您可以在BarInline中将所有字段设为只读。

class BarInline(admin.StackedInline):
    model = Bar
    readonly_fields = ('id', 'name', 'foo')
    extra = 0

对于“添加”功能,您可以修改内联模板或更简单,可以在FooAdmin中添加自定义字段,例如:

class FooAdmin(admin.ModelAdmin):
    list_display = ('name')
    fields = ('name', 'custom_add_bar')
    inlines = [BarInline]

    def custom_add_bar(self, obj):
        add_url = reverse('admin:appname_bar_add')
        return mark_safe(f'<a href="{add_url}">Add Bar</a>')

Documentation for reversing admin urls

答案 1 :(得分:1)

admin.py

from django.urls import reverse
from django.utils.html import format_html_join

@admin.register(Foo)
class FooAdmin(admin.ModelAdmin):
    list_display = ('name')
    fields = ('name', get_related, )
    readonly_fields = (get_related, )

    def get_related(self, instance):
        obj = instance.bar_set.all()
        return format_html_join(
            ',',
            '<a href="{}">{}</a>',
            ((
                reverse('admin:{{ app_label }}_bar_change', args=(c.id,)), 
                c.name
            ) for c in obj),
        )

您可以创建一个可调用的readonly field,它将返回包装在相关admin url中的每个关系的反向html code

这将导致类似以下内容:

  

“您的只读字段”:link1,link2,link3