2010-01-22 121 views
31

我定义了几种模式:期刊,卷volume_scanInfo等Django的InlineModelAdmin:显示部分内嵌模型,并链接到完整的模型

一本期刊可以有更多的容量和体积可以有更多的scanInfo。

我想要做的是:

    在期刊的管理页面
  • 我想有卷内联(完成)的列表
  • 前面列表中的每个卷连接到其管理页面在那里我可以显示表单来编辑内容的“扫描信息”列表和内联列表。

,所以我想有这样的:

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. 

任何想法?

感谢, 乔瓦尼

+0

非常好的问题。这种功能应该内置。 – 2011-11-09 07:53:41

+0

iI内置。它在这里回答(show_change_link)自django 1.8以来:http://stackoverflow.com/a/28170958/493272 – SpiRail 2016-05-19 21:48:46

+0

我知道,但问题是6岁: - ) 我会更新答案,所以很明显有这个新功能。 – 2016-05-20 13:33:25

回答

29

UPDATE: 由于Django的1.8,这是建立在

this answerthe official documentation

OLD答:

最后我找到了一个简单的解决方案。

我创建了一个名为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 %} 

然后,我创建继承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然后当我定义了一个新的内嵌,我只有用我的LinkedInline而不是正常的InlineModelAdmin

我希望它对其他人有用。

乔瓦尼

+0

当您保存子模型页面时,是否会回到父模型页面? – 2011-11-09 07:47:33

+0

你是什么意思? – 2011-11-30 10:19:44

+0

如果您正在编辑链接到日记帐的完整卷模型,那么当您保存时,它会自动返回到日记本版本页面吗? – 2011-12-01 08:56:01

3

你试试Reversing admin URL系统?
,可以给类似的东西(在日记页):

<ul> 
{% for volume in original.volume_set.all %} 
    <li> 
    <a href="{% url admin:yourapp_volume_change volume.id %}">Edit {{ volume }} 
    </a> 
    </li> 
{% endfor %} 
</ul> 
+0

+1,用于反转管理URL的引用。 – rluba 2012-09-03 06:43:50

25

更新:

由于Django的1.8,这是现在built-in。 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为readonly领域:

class VolumeInline(admin.TabularInline): 
    readonly_fields = ['selflink',] 
    model = Volume 

这对我有效。

+3

如果您使用'fields'选项,则需要将它放在'readonly_fields'后面 – 2013-02-21 17:22:26

+1

@uszywieloryba:在Django-1.4.x中不真实。无论如何,'selflink'必须在'fields'或'fieldsets'中。 – Stan 2013-05-30 14:27:25

+0

我更喜欢在models.py中编写代码,而不是在temaplates中编写代码!谢谢 – Marconius 2013-06-04 15:21:55

2

经过一番捣乱之后,我可以使用reverse()在InlineAdmin和TabularInline中完成这项工作。至少有TabularInline,要链接必须在“readonly_fields”

# create a read-only inline with the first field linked 
from django.core import urlresolvers 
class YOUR_MODEL_Inline(LinkedTabularInline): 
    max_num = 0 # remove the "Add another ..." link 
    model = YOUR_MODEL_NAME 
    fk_name = "YOUR_FOREIGN_KEY_NAME" 
    fields = [ 'link_name', ] # , 'field1', 'field2', 'etc' ] 
    readonly_fields = fields 
    can_delete = False 
    def link_name(self, obj): 
     if obj.pk: 
      url = urlresolvers.reverse('admin:%s_%s_change' 
       % (obj._meta.app_label, obj._meta.module_name), args=[obj.id]) 
      # obj.MODEL_FIELD can be a text string or whatever you want 
      return '<a href="{0}">{1}</a>'.format(url, obj.MODEL_FIELD) 
    link_name.allow_tags = True 
    link_name.short_description = "MODEL_FIELD" 

如果你要链接到的变化列表,而不是更改视图,您可以修改反向()调用上市现场。更改列表不需要对象ID。

url = urlresolvers.reverse('admin:%s_%s_changelist' 
     % (obj._meta.app_label, obj._meta.module_name)) 
    return '<a href="{0}">{1}</a>'.format(url, obj.name) 

如果你要链接到对象的一个​​子集,可以将网址添加参数:

return '<a href="{0}?YOUR_MODEL_FIELD__id__exact={1}">{2}</a>'.format(url, obj.id, obj.name) 
13

下面是基于一些其他的答案的可重复使用的混入。这很方便,因为它可以同时处理Tabular和Stacked内联,并且不会占用您的模型或管理代码。

# 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] 
+3

非常有帮助和整洁。我需要在代码顶部添加这个'from django.core.urlresolvers import reverse' – Charlesliam 2014-01-24 03:02:37

+0

我想知道是否可以自动使用很多2个字段集合,在哪里有'model = ModelA.modelbs.through'? 它需要检测这个(也许通过'_meta.auto_created'?)并相应地创建编辑链接。 – blueyed 2014-06-20 00:36:16

8

Django 1.8+ this is now much easier。只需添加show_change_link = TrueTabularInlineStackedInline子类,像这样:

class VolumeInline(admin.TabularInline): 
    fields = ['volumenumber'] 
    model = Volume 
    extra = 1 
    show_change_link = True 

而且Django会自动添加一个链接到充满变化形式,每个联项目,如果该模式有自己的注册ModelAdmin

+0

现在应该接受回答 – 2016-11-13 03:14:55