Django Admin:将超链接添加到相关模型

Django Admin: Add Hyperlink to related model

我想添加到相关模型的超链接Training

最好有声明式解决方案,因为我想使用 这在几个地方。

“铅笔”图标会在弹出窗口中打开相关模型 window。那不是我想要的。我想要相关模型的简单超链接。

顺便说一句,如果你使用“raw_id_fields”,那么结果正是我要找的:有一个超链接到这个 ForeignKey 的相应管理界面。

有几种方法。这是一个。

添加一些 javascript 来改变现有的 link 行为。在 overridden admin template admin/widgets/related_widget_wrapper.html 末尾添加以下脚本。它删除了触发模式的 class 并将 link 更改为对象。

它只会在 id_company 字段被触发。根据您的需要更改。

{% block javascript %}
<script>
'use strict';
{
    const $ = django.jQuery;

    function changeEditButton() {
        const edit_btn = document.getElementById('change_id_company');
        const value = edit_btn.previousElementSibling.value;
        const split_link_template = edit_btn.getAttribute('data-href-template').split('?');
        edit_btn.classList.remove('related-widget-wrapper-link');
        edit_btn.setAttribute('href', split_link_template[0].replace('__fk__', value));
    };

    $(document).ready(function() {
        changeEditButton();
        $('body').on('change', '#id_company', function(e) {
            changeEditButton();
        });
    });
}
</script>
{% endblock %}

也可以修改此代码以触发所有编辑按钮,而不仅仅是公司编辑按钮。

名为 RelatedFieldWidgetWrapper 的 class 正在 Django 管理页面上显示图标,因此您需要覆盖相同的。因此,创建一个自定义 class,如下所示,

from django.contrib.admin.widgets import RelatedFieldWidgetWrapper


class CustomRelatedFieldWidgetWrapper(RelatedFieldWidgetWrapper):
    template_name = 'admin/widgets/custom_related_widget_wrapper.html'

    @classmethod
    def create_from_root(cls, root_widget: RelatedFieldWidgetWrapper):
        # You don't need this method of you are using the MonkeyPatch method
        set_attr_fields = [
            "widget", "rel", "admin_site", "can_add_related", "can_change_related",
            "can_delete_related", "can_view_related"
        ]
        init_args = {field: getattr(root_widget, field) for field in set_attr_fields}
        return CustomRelatedFieldWidgetWrapper(**init_args)

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        rel_opts = self.rel.model._meta
        info = (rel_opts.app_label, rel_opts.model_name)
        context['list_related_url'] = self.get_related_url(info, 'changelist')
        return context

看,上下文变量list_related_url就是我们这里需要的相对路径。现在,创建一个 HTML 文件来渲染输出,

#File: any_registered_appname/templates/admin/widgets/custom_related_widget_wrapper.html

{% extends "admin/widgets/related_widget_wrapper.html" %}
{% block links %}
    {{ block.super }}
    <a href="{{list_related_url}}">- Link To Related Model -</a>
{% endblock %}

如何连接?

方法一:猴子补丁

# admin.py

# other imports
from ..widgets import CustomRelatedFieldWidgetWrapper
from django.contrib.admin import widgets

widgets.RelatedFieldWidgetWrapper = CustomRelatedFieldWidgetWrapper # monket patch

方法 2:覆盖 ModelAdmin

# admin.py
class AlbumAdmin(admin.ModelAdmin):
    hyperlink_fields = ["related_field_1"]

    def formfield_for_dbfield(self, db_field, request, **kwargs):
        formfield = super().formfield_for_dbfield(db_field, request, **kwargs)
        if db_field.name in self.hyperlink_fields:
            formfield.widget = CustomRelatedFieldWidgetWrapper.create_from_root(
                formfield.widget
            )
        return formfield

结果