【问题标题】:Django Admin: Add Hyperlink to related modelDjango Admin:将超链接添加到相关模型
【发布时间】:2021-10-14 07:11:47
【问题描述】:

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

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

“铅笔”图标在弹出窗口中打开相关模型。那不是我想要的。我想要一个指向相关模型的普通超链接。

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

【问题讨论】:

  • 下拉列表旁边的编辑链接(铅笔图标)是什么?它会打开一个编辑选定对象的窗口。
  • @solarissmoke “铅笔”图标在弹出窗口中打开相关模型。那不是我想要的。我想要一个指向相关模型的普通超链接。

标签: django django-admin


【解决方案1】:

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

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

结果

【讨论】:

【解决方案2】:

有几种方法可以去。这是一个。

添加一些改变现有链接行为的 javascript。在overridden admin templateadmin/widgets/related_widget_wrapper.html 的末尾添加以下脚本。它删除了触发模态的类并更改了到对象的链接。

它只会被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 %}

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

【讨论】:

    猜你喜欢
    • 2012-02-24
    • 1970-01-01
    • 2021-06-22
    • 2012-06-30
    • 2014-09-04
    • 2011-09-19
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多