在django admin中为内联项添加完整更改表单的链接?

Dav*_*Eyk 36 django hyperlink django-forms django-admin

我有一个对象的标准管理员更改表单,通常的StackedInline表单用于ForeignKey关系.我希望能够将每个内联项链接到相应的完整大小的更改表单,因为内联项具有自己的内联项,我无法嵌套它们.

我已经尝试了从自定义小部件到自定义模板的所有内容,并且无法使任何工作.到目前为止,我以片段形式看到的"解决方案"似乎并不适用于内联.我正准备尝试使用jQuery进行一些DOM攻击,以使其正常工作并继续前进.

我希望我一定会错过一些非常简单的事情,因为这看起来像是一项简单的任务!

使用Django 1.2.

Flo*_*ian 84

有一个叫show_change_linkDjango 1.8 的房产.

  • 为什么这不是顶级? (3认同)
  • 快速注意,您必须在管理站点(而不仅仅是内联)中注册模型,否则更改链接根本不会显示在内联上方(Django 3.2)。 (2认同)

小智 45

我在admin.py中执行了以下操作:

from django.utils.html import format_html
from django.core.urlresolvers import reverse

class MyModelInline(admin.TabularInline):
    model = MyModel

    def admin_link(self, instance):
        url = reverse('admin:%s_%s_change' % (instance._meta.app_label,  
                                              instance._meta.module_name),
                      args=(instance.id,))
        return format_html(u'<a href="{}">Edit</a>', url)
        # … or if you want to include other fields:
        return format_html(u'<a href="{}">Edit: {}</a>', url, instance.title)

    readonly_fields = ('admin_link',)
Run Code Online (Sandbox Code Playgroud)

  • 似乎在Django 1.8而不是`instance._meta.module_name`中它应该是`instance._meta.model_name` (6认同)

Luk*_*ski 11

我有类似的问题,我想出了自定义小部件加上一些模型形式的调整.这是小部件:

from django.utils.safestring import  mark_safe    

class ModelLinkWidget(forms.Widget):
    def __init__(self, obj, attrs=None):
        self.object = obj
        super(ModelLinkWidget, self).__init__(attrs)

    def render(self, name, value, attrs=None):
        if self.object.pk:
            return mark_safe(
                u'<a target="_blank" href="../../../%s/%s/%s/">%s</a>' %\
                      (
                       self.object._meta.app_label,
                       self.object._meta.object_name.lower(),
                       self.object.pk, self.object
                       )
            )
        else:
            return mark_safe(u'')
Run Code Online (Sandbox Code Playgroud)

现在因为每个内联的小部件需要在构造函数中获得不同的对象,所以不能只以标准方式设置它,而是在Form的init方法中:

class TheForm(forms.ModelForm):
    ...
    # required=False is essential cause we don't
    # render input tag so there will be no value submitted.
    link = forms.CharField(label='link', required=False)

    def __init__(self, *args, **kwargs):
        super(TheForm, self).__init__(*args, **kwargs)
        # instance is always available, it just does or doesn't have pk.
        self.fields['link'].widget = ModelLinkWidget(self.instance)
Run Code Online (Sandbox Code Playgroud)

我希望有所帮助.

  • 此外,这可能容易受到XSS攻击(取决于所呈现的对象及其来源),并且您真的不希望管理员中的那些 - 使用Django模板而不是python的%来渲染字符串. (2认同)

Joe*_*avy 9

目前公认的解决方案是好的工作,但它已经过时了.

从Django 1.3开始,有一个内置属性show_change_link = True可以解决这个问题.

这可以添加到任何StackedInline或TabularInline对象.例如:

class ContactListInline(admin.TabularInline):
    model = ContactList
    fields = ('name', 'description', 'total_contacts',)
    readonly_fields = ('name', 'description', 'total_contacts',)
    show_change_link = True
Run Code Online (Sandbox Code Playgroud)

结果将是这样的:

使用show_change_link的表格内联

  • 但是如果我想让标题成为超链接,而不是标题旁边的标签怎么办? (3认同)