10

模型.py

class Menu(models.Model):

    ...
    has_submenu=models.BooleanField(default=1)
    page=models.ForeignKey(Page,null=True)

我希望 django admin 仅在 has_submenu 复选框为 false 时才显示页面属性(所以 django-admin 必须为我编写一些 javascript :))

也许我必须扩展render_change_form方法

有什么建议吗?

4

4 回答 4

23

您可以在 Django 管理员中使用 jQuery

class MenuAdmin(admin.ModelAdmin):
    # ...
    class Media:
        js = ('/static/admin/js/hide_attribute.js',)

ModelAdminInlineModelAdmin有一个media属性返回一个媒体对象列表,这些对象存储表单和/或表单集的 JavaScript 文件的路径。

hide_attribute.js 的内容:

hide_page=false;
django.jQuery(document).ready(function(){
    if (django.jQuery('#id_has_submenu').is(':checked')) {
        django.jQuery(".page").hide();
        hide_page=true;
    } else {
        django.jQuery(".page").show();
        hide_page=false;
    }
    django.jQuery("#id_has_submenu").click(function(){
        hide_page=!hide_page;
        if (hide_page) {
            django.jQuery(".page").hide();
        } else {
            django.jQuery(".page").show();
        }
    })
})

命名空间:

为了避免与用户提供的脚本或库发生冲突,Django 的 jQuery(版本 3.3.1)被命名为django.jQuery.

于 2013-04-13T19:39:51.840 回答
3

如何覆盖get_formModelAdmin 上的方法,如下所示:

class MenuModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        self.exclude = []
        if obj and obj.has_submenu:
            self.exclude.append('page')
        return super(MenuModelAdmin, self).get_form(request, obj, **kwargs)

另外,请参阅get_form 文档

于 2013-04-12T20:23:43.400 回答
1

您可以扩展 Django 管理模板。

只需遵循以下结构:

在整个项目中:

templates/admin/change_form.html

跨应用程序

templates/admin/<my_app>/change_form.html

跨模型

templates/admin/<my_app>/<my_model>/change_form.html

在您的情况下,看起来您只需要扩展 Menu 模型。我会做以下事情:

  1. 从django 文件夹中获取change_form.html teamplate
  2. 在对象循环中,查找页面字段
  3. has_submenu进行条件检查以决定是否显示页面属性
于 2013-04-12T20:37:25.473 回答
1

实际上,我不得不稍微修改一下,并想我会分享我在这里所做的事情,以防其他人偶然发现这篇文章。我必须考虑三个主要领域:

  1. 经常出错,因为它在准备好之前尝试加载 django.jQuery。
  2. 隐藏一般不工作(不知道为什么)
  3. 想要做相反的事情,除非选中该选项,否则隐藏。

所以,这为我解决了所有这三个问题。我们执行以下操作:

  1. 延迟调用函数
  2. 隐藏 .form-row.field-, 以隐藏整行(我建议使用 chrome 检查功能来查找要隐藏的行的名称。)
  3. 我们做相反的事情,一旦页面加载完成就隐藏该部分,然后如果选中该框则取消隐藏。

所以这是我的最终代码:

window.addEventListener("load", function() {
    (function() {
        show_page=false;
        django.jQuery(document).ready(function(){
            if (django.jQuery('#id_override_timeline').is(':checked')) {
                django.jQuery(".form-row.field-next_milestone").show();
                show_page=true;
            } else {
                django.jQuery(".form-row.field-next_milestone").hide();
                show_page=false;
            }
            django.jQuery("#id_override_timeline").click(function(){
                show_page=!show_page;
                if (show_page) {
                    django.jQuery(".form-row.field-next_milestone").show();
                } else {
                    django.jQuery(".form-row.field-next_milestone").hide();
                }
            })
        })
    })(django.jQuery);
});


我希望这可以帮助其他偶然发现这篇文章的人!

于 2021-09-08T20:22:51.333 回答