Django InlineModelAdmin:部分显示内联模型并链接到完整模型
我定义了几个模型:期刊、卷、卷的扫描信息等等。
一个期刊可以有多个卷,而一个卷可以有多个扫描信息。
我想要做的是:
- 在期刊的管理页面上,我想要把卷的列表显示在一起(这个已经完成)
- 把之前列表中的每个卷连接到它的管理页面,这样我就可以显示一个表单来编辑这个卷,并且把它的“扫描信息”列表也显示在一起。
所以我想要有这样的东西:
Journal #1 admin page
[name]
[publisher]
[url]
.....
list of volumes inline
[volume 10] [..(other fields)..] <a href="/link/to/volume/10">Full record</a>
[volume 20] [..(other fields)..] <a href="/link/to/volume/20">Full record</a>
然后
Volume #20 admin page
[volume number]
[..(other fields)...]
......
list of the scan info inline
[scan info 33] [..(other fields)..] <a href="/link/to/scaninfo/33">Full record</a>
[scan info 44] [..(other fields)..] <a href="/link/to/scaninfo/44">Full record</a>
我尝试做的是定义一个模型方法来生成代码,并试图在定义“卷内联”的管理类中使用它,但没有成功。
换句话说,
模型“卷”里面有类似这样的内容:
def selflink(self):
return '<a href="/admin/journaldb/volume/%s/">Full record</a>' % self.vid
selflink.allow_tags = True
还有
class VolumeInline(admin.TabularInline):
fields = ['volumenumber', 'selflink']
model = Volume
extra = 1
但是这给出了以下错误:
Exception Value: 'VolumeInline.fields' refers to field 'selflink' that is missing from the form.
有什么想法吗?
谢谢,
乔瓦尼
6 个回答
14
这里有一个可以重复使用的混合代码,它是基于其他一些回答制作的。这个混合代码很方便,因为它可以同时适用于表格形式和堆叠形式的内联显示,而且不会让你的模型或管理代码变得复杂。
# put this somewhere like admin_helpers.py
from django.core.urlresolvers import reverse
class InlineEditLinkMixin(object):
readonly_fields = ['edit_details']
edit_label = "Edit"
def edit_details(self, obj):
if obj.id:
opts = self.model._meta
return "<a href='%s' target='_blank'>%s</a>" % (reverse(
'admin:%s_%s_change' % (opts.app_label, opts.object_name.lower()),
args=[obj.id]
), self.edit_label)
else:
return "(save to edit details)"
edit_details.allow_tags = True
# admin.py
class VolumeInline(InlineEditLinkMixin, admin.TabularInline):
fields = ['foo', 'bar', 'edit_details']
class JournalAdmin(admin.ModelAdmin):
inlines = [VolumeInline]
class ScanInfoInline(InlineEditLinkMixin, admin.StackedInline):
fields = ['foo', 'bar', 'edit_details']
class JournalAdmin(admin.ModelAdmin):
inlines = [ScanInfoInline]
25
更新:
从Django 1.8开始,这个功能现在是内置的了。
对于Django版本小于等于1.7的回答:
把你的代码放在models.py文件里,并使用条件语句:
def selflink(self):
if self.id:
return "<a href='/link/to/volume/%s' target='_blank'>Edit</a>" % str(self.id)
else:
return "Not present"
selflink.allow_tags = True
在admin.py文件中,把selflink添加为只读字段:
class VolumeInline(admin.TabularInline):
readonly_fields = ['selflink',]
model = Volume
这个方法对我有效。
29
更新:从Django 1.8开始,这个功能已经内置了。
旧回答:
最后我找到了一种简单的解决方案。
我创建了一个新的模板,叫做 linked.html
,它是 tabular.html
的一个副本,然后我添加了一段代码来创建链接。
{% if inline_admin_form.original.pk %}
<td class="{{ field.field.name }}">
<a href="/admin/{{ app_label }}/{{ inline_admin_formset.opts.admin_model_path }}/{{ inline_admin_form.original.pk }}/">Full record</a>
</td>
{% endif %}
接着我创建了一个新的模型 LinkedInline
,它继承自 InlineModelAdmin
。
#override of the InlineModelAdmin to support the link in the tabular inline
class LinkedInline(admin.options.InlineModelAdmin):
template = "admin/linked.html"
admin_model_path = None
def __init__(self, *args):
super(LinkedInline, self).__init__(*args)
if self.admin_model_path is None:
self.admin_model_path = self.model.__name__.lower()
然后当我定义一个新的内联时,只需要使用我的 LinkedInline
,而不是普通的 InlineModelAdmin
。
希望这对其他人有帮助。
乔瓦尼