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

Posted

技术标签:

【中文标题】在 django admin 中为内联项目添加完整更改表单的链接?【英文标题】:Adding links to full change forms for inline items in django admin? 【发布时间】:2011-02-20 20:51:53 【问题描述】:

我有一个对象的标准管理员更改表单,以及用于 ForeignKey 关系的常用 StackedInline 表单。我希望能够将每个内联项链接到其相应的全尺寸更改表单,因为内联项具有自己的内联项,我不能嵌套它们。

我已经尝试了从自定义小部件到自定义模板的所有方法,但都无法正常工作。到目前为止,我以简单的 sn-ps 形式看到的“解决方案”似乎不适用于内联。我正准备尝试使用 jQuery 进行一些 DOM hacking,以使其正常工作并继续前进。

我希望我一定错过了一些非常简单的事情,因为这似乎是一项简单的任务!

使用 Django 1.2。

【问题讨论】:

我发现***.com/questions/2120813给出的答案更好。 Django >= 1.8,使用show_change_link***.com/a/28170958/3218806 【参考方案1】:

我遇到了类似的问题,我想出了自定义小部件以及对模型表单的一些调整。这是小部件:

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'')

现在,由于每个内联小部件需要在构造函数中获取不同的对象,您不能只以标准方式设置它,而是在 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)

【讨论】:

我没有时间尝试这个,但它看起来应该可以工作。 :) 谢谢。 这是一个很好的解决方案,结合***.com/questions/5197280/…可以做得更好 此外,这可能容易受到 XSS 攻击(取决于呈现的对象以及它们来自何处),并且您真的不希望管理员中的那些 - 使用 Django 模板呈现字符串而不是 python 的 %.【参考方案2】:

为此目的有一个模块。退房: django-relatives

【讨论】:

【参考方案3】:

这里目前接受的解决方案很好,但已经过时了。

从 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

结果将是这样的:

【讨论】:

但是如果我希望标题是超链接,而不是标题旁边的标签呢?【参考方案4】:

从 Django 1.8 开始有一个名为 show_change_link 的属性。

【讨论】:

快速注意,您必须在管理站点中注册模型(不仅仅是内联),否则更改链接根本不会显示在内联(Django 3.2)上方。【参考方案5】:

我在我的 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',)

【讨论】:

我已将此添加到我的管理员,但我没有看到链接。该列已添加。有什么想法吗? 不错的解决方案。很干净 保存编辑表单时,应该回到原来的父编辑页面而不是被编辑对象的更改列表。 似乎在 Django 1.8 中而不是 instance._meta.module_name 它应该是 instance._meta.model_name 真正的 module_name 应该是 model_name【参考方案6】:

上面昆汀的回答有效,但你还需要指定fields = ('admin_link',)

【讨论】:

【参考方案7】:

我认为:args=[instance.id] 应该是 args=[instance.pk]。它对我有用!

【讨论】:

以上是关于在 django admin 中为内联项目添加完整更改表单的链接?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django admin 上添加只读内联

有没有办法在 Django 中为内联管理表单设置单独的页面?

Django admin 不同的内联用于更改和添加视图

在 Django admin 中添加内联多对多对象

Django Admin:动态添加内联

Django Admin Cookbook-22如何将一对一关系添加为Admin内联字段