Django Admin - RelatedObjectLookups - 它如何刷新和设置父窗口上的选择?

Posted

技术标签:

【中文标题】Django Admin - RelatedObjectLookups - 它如何刷新和设置父窗口上的选择?【英文标题】:Django Admin - RelatedObjectLookups - How Does it refresh and set the select on the parent window? 【发布时间】:2011-08-10 07:27:36 【问题描述】:

我想让我的一个表单像管理页面一样工作,所以我想我会查看代码并了解它是如何工作的。

具体来说,我希望用户能够单击选择列表旁边的“+”图标并被带到管理页面的弹出表单以添加新项目。

当他们在那里输入新项目时,我希望该新项目出现在选择框中并被选中(就像此功能在管理页面上的工作方式一样)。

我将管理 js 库复制到我自己的模板中,并让我的链接调用相同的 JS 函数并且弹出窗口确实打开了,但是在我保存一个新对象后,弹出窗口变为空白而不是关闭,什么也没有发生在父页面上。

这是我在页面中输入的内容:

...
<td>
    <div class="fieldWrapper">
        <select name="form-0-plasmid" id="id_form-0-plasmid">
        ...
        </select>
        <a href="/admin/VirusTracker/plasmid/add/" class="add-another" id="add_id_plasmid" onclick="return showAddAnotherPopup(this);"> <img src="/media/admin/img/admin/icon_addlink.gif"   /></a>
    </div>
</td>
...

我尝试单步执行管理表单上的 javascript 以查看它是如何工作的,但我没有看到任何会关闭窗口或填充父窗口选择的内容。

提前感谢您的帮助。

更新 3

运行dismissAddAnotherPopup 时出现此javascript 错误

"SelectBox is not defined"

dismissAddAnotherPopup 中哪个指向这一行

SelectBox.add_to_cache(toId, o);

我以为我知道 Javascript,但我不知道该变量应该来自哪里:-(

更新 2

似乎一切正常。在弹出窗口上单击保存后,我得到一个空白页。这是该页面的来源:

<script type="text/javascript">opener.dismissAddAnotherPopup(window, "9", "CMV_flex_myr_GENE1_._._WPRE_BGH");</script>

所以看起来这个 javascript 没有被执行或失败。

更新

这是丹尼尔提到的相关代码。所以唯一的问题是这段代码要么没有触发,要么触发不正确。

django/contrib/admin/options.py:

...
        if request.POST.has_key("_popup"):
            return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
                # escape() calls force_unicode.
                (escape(pk_value), escapejs(obj)))
...

/media/admin/js/admin/RelatedObjectLookups.js:

function dismissAddAnotherPopup(win, newId, newRepr) 
    // newId and newRepr are expected to have previously been escaped by
    // django.utils.html.escape.
    newId = html_unescape(newId);
    newRepr = html_unescape(newRepr);
    var name = windowname_to_id(win.name);
    var elem = document.getElementById(name);
    if (elem) 
        if (elem.nodeName == 'SELECT') 
            var o = new Option(newRepr, newId);
            elem.options[elem.options.length] = o;
            o.selected = true;
         else if (elem.nodeName == 'INPUT') 
            if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) 
                elem.value += ',' + newId;
             else 
                elem.value = newId;
            
        
     else 
        var toId = name + "_to";
        elem = document.getElementById(toId);
        var o = new Option(newRepr, newId);
        SelectBox.add_to_cache(toId, o);
        SelectBox.redisplay(toId);
    
    win.close();

【问题讨论】:

【参考方案1】:

好的,javascript 只是使用启动元素的 id 属性来标识要更新的选择字段。 (从开头删除 'add_' 之后)。

所以我只是更改了链接的 id 属性以匹配模板中选择元素的 id:

<a href="/admin/VirusTracker/plasmid/add/" class="add-another" id="add_id_field.html_name" onclick="return showAddAnotherPopup(this);"> <img src="/media/admin/img/admin/icon_addlink.gif"   /></a>

哇,我希望这已经记录在某个地方!我为此浪费了几个小时。

(请参阅我对问题的更新,了解有关这一切如何运作的更多技术细节。)

【讨论】:

我遇到了同样的问题,但我不明白“选择元素 id”在哪里(在哪个模板中?)。我正在使用本指南:link 您能否为 javascript 初学者提供更多信息? 刚刚遇到同样的问题(10 年后,但使用 Django-AddAnother 库,它基本上做同样的事情)。如需进一步参考:如果使用 Field 类以 Crispy 形式添加小部件,则 d̲o̲n̲'̲t̲ 将属性设置为上述 id(即 d̲o̲n̲'̲t̲ 使用Field('keywords', id="id_keywords"), 用于关键字字段);不知何故,id 属性没有按应有的方式设置,并且弹出窗口将无法处理 ajax(导致与此处指出的相同的错误)。 ***.com/questions/69313268/…你能帮帮我吗【参考方案2】:

诀窍 - 实际上它有点像 hack - 当您在管理员的弹出窗口中单击保存时会发生什么。

如果您查看django.contrib.options.ModelAdmin 中的response_add 代码,您会发现当您在弹出窗口中保存项目时,管理员会返回一个仅由一段Javascript 组成的HttpResponse。该JS调用父窗口中的dismissAddAnotherPopup函数,关闭弹窗并适当设置表单值。

将此功能复制到您自己的应用中相当简单。

更新后编辑如果管理员 javascript 不起作用,通常是因为它依赖于 jsi18n 代码 - 您通过 URL(不是静态路径)包含该代码:

<script type="text/javascript" src="/admin/jsi18n/"></script>

【讨论】:

啊,我现在明白了。但是由于我的弹出窗口是管理页面自己的弹出窗口,为什么那一点 javascript 不能按原样工作呢?我是否需要以某种方式将其指向新的父窗口? 我用我的最新发现更新了我的问题。如果您有任何想法,请告诉我。 ***.com/questions/69313268/…你能看看这个问题吗?【参考方案3】:

我在刷新父窗口中的选择时遇到了同样的问题,我解决了这个doc

现在一切正常

编辑 1:

我试图使用 Select2 使选择更漂亮,单选工作正常,多选让我很头疼,由于某种原因没有更新父表单中的信息。

以前有人试过吗?

【讨论】:

以上是关于Django Admin - RelatedObjectLookups - 它如何刷新和设置父窗口上的选择?的主要内容,如果未能解决你的问题,请参考以下文章

django 配置管理后台,出现多个 admin/admin/admin

django1.6 admin不能登录

django 自带的admin登录页面可以换自己做的登录页面吗?

django admin能加逻辑操作吗?

django的admin界面怎么没有样式

怎么使用django里面admin的部分内容