代码之家  ›  专栏  ›  技术社区  ›  Giovanni Di Milia

django inlinemodeladmin:显示部分内联模型并链接到完整模型

  •  32
  • Giovanni Di Milia  · 技术社区  · 15 年前

    我定义了几个模型:日志、卷、卷扫描信息等。

    日志可以有更多的卷,卷可以有更多的扫描信息。

    我想做的是:

    • 在日记账的管理页中,我想将卷列表内联(完成)
    • 将上一个列表中的每个卷连接到其管理页面,在该页面上我可以显示表单以编辑卷及其“扫描信息”的内联列表。

    所以我想要一些像:

    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>
    

    我试图做的是定义一个创建代码的模型方法,并尝试在管理中定义“volume inline”的类内使用它,但它不起作用。

    换句话说

    模型“volume”的内部类似于:

    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 回复  |  直到 7 年前
        1
  •  29
  •   Community kfsone    7 年前

    更新: 从django 1.8开始,这是内置的。

    this answer the official documentation .

    老回答:

    最后我找到了一个简单的解决办法。

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

    当我定义一个新的内联时,我只需要使用 林肯线 而不是正常的 内联模型管理 .

    我希望它能对其他人有用。

    乔凡尼

        2
  •  25
  •   hurturk    7 年前

    更新:

    从django 1.8开始,现在是 built-in .

    django<=1.7的答案:

    保留代码 模特儿 有条件的情况下:

    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
    

    行政管理部门 ,添加selflink为 readonly 领域:

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

    这对我很有用。

        3
  •  13
  •   blueyed    10 年前

    下面是一个基于其他一些答案的可重用mixin。这很方便,因为它既可以处理表格式内联线,也可以处理堆叠式内联线,而且不会损坏您的模型或管理代码。

    # 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]
    
        4
  •  8
  •   Carl Meyer    9 年前

    Django 1.8+ this is now much easier . 只要添加 show_change_link = True 对你 TabularInline StackedInline 子类,如下所示:

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

    如果模型已经注册,django将自动为每个内联项添加到完整更改表单的链接 ModelAdmin .

        5
  •  3
  •   Pierre de LESPINAY    11 年前

    你试过 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>
    
        6
  •  2
  •   Eli Burke    12 年前

    经过一些修改之后,我可以使用reverse()在内联管理和表格行中执行此操作。至少在tabularinline中,要链接的字段 必须 列在“只读字段”中

    # 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"
    

    如果要链接到更改列表而不是更改视图,可以修改reverse()调用。变更列表不需要对象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)
    

    如果要链接到对象的子集,可以向url添加参数:

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