Django 管理弹出功能
这个话题相当普遍(最明确的细节在这里:http://www.hoboes.com/Mimsy/hacks/replicating-djangos-admin/),但我仍然遇到问题.我正在尝试使用管理站点中使用的加号"按钮功能,可以在其中向链接条目添加额外的外键.在管理站点中,将显示一个弹出窗口,允许用户提交一个新字段,然后在原始表单中填充该新值.
This topic is fairly common (most explicitly detailed here: http://www.hoboes.com/Mimsy/hacks/replicating-djangos-admin/), but I'm still having trouble with it. I'm trying to use the "plus" button functionality used in the admin site where one can add an additional foreign key to a linked entry. In the admin site, a popup displays allowing the user to submit a new field and then that new value is populated on the original form.
我认为我的问题集中在包含这一行:
I think my issue centers around the inclusion of this line:
在 base.html 模板和 popadd.html 模板中.单击加号按钮不会打开新窗口.popadd 模板只是在同一个选项卡中加载.并且提交新条目不会让用户回到原来的表单.
within the base.html template and the popadd.html template. Clicking the plus button does not bring up a new window. The popadd template simply loads in the same tab. And submitting a new entry does not take the user back to the original form.
管理站点正常运行.我在 settings.py 文件中包含 ADMIN_MEDIA_PREFIX = '/media/admin/' .它与 RelatedObjectLookups.js 所在的位置有关吗?它目前位于我的项目文件夹之外的管理目录中.我必须创建一个符号链接吗?
The admin site is functional. I am including ADMIN_MEDIA_PREFIX = '/media/admin/' in the settings.py file. Does it have something to do with where the RelatedObjectLookups.js lives? It's currently in an admin directory outside of my project folder. Do I have to create a symlink?
对不起,菜鸟问题.希望有任何建议(尽可能详细).
Sorry for the noob questions. Would appreciate any suggestions (as detailed as possible).
推荐答案
按照下面概述的步骤,您可以重新创建 Django 管理员的相关对象弹出功能,而无需创建任何自定义小部件、视图和 url.这些步骤假设您正在尝试让这个弹出窗口在您自己的自定义管理站点中工作,该站点是 Django 管理员的子类.
Following the steps outlined below will allow you to recreate Django admin's related object pop-up functionality without having to create any custom widgets, views, and urls. These steps assume you are trying to get this pop-up working in your own custom admin site which subclasses Django's admin.
让我们假设以下两个模型 Book 和 Author,具有从 Book 到 Author 的 FK.还假设我们希望能够在创建/编辑书籍时使用相关对象弹出窗口来添加作者:
Lets assume the following two models Book and Author, with an FK from Book to Author. Lets also assume that we'll want the ability to use the Related Object Pop-Up to add an Author when creating/editing a Book:
[app_name]/models.py:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=200)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=200)
让我们创建我们的自定义管理站点:
Lets create our custom admin site:
[app_name]/sites.py:
from django.contrib.admin.sites import AdminSite
my_admin_site = AdminSite(name='my_custom_admin')
我们的自定义管理站点将注册两个 ModelAdmin 以允许用户添加/编辑/删除 Book 和 Author 模型:
Our custom admin site will register two ModelAdmins to allow users to add/edit/delete both the Book and Author models:
[app_name]/admin.py:
from django.contrib.admin.options import ModelAdmin
from [app_name].forms import BookForm # We'll create this form below
from [app_name].models import Author, Book
from [app_name].sites import my_admin_site
class BookModelAdmin(ModelAdmin):
form = BookForm()
# Register both models to our custom admin site
my_admin_site.register(Author, ModelAdmin)
my_admin_site.register(Book, BookModelAdmin)
现在,我们将设置上面 BookModelAdmin
中使用的 BookForm
.这就是魔法发生的地方.有关 RelatedFieldWidgetWrapper api 的更多信息,点击这里:
Now, we'll setup the BookForm
which is used in the BookModelAdmin
above. This is where the magic happens. For more info on the RelatedFieldWidgetWrapper api, click here:
[app_name]/forms.py:
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper
from django import forms
from [app_name].models import Book
from [app_name].sites import my_admin_site
class BookForm(forms.ModelForm):
author = Book._meta.get_field('author').formfield(
widget=RelatedFieldWidgetWrapper(
Book._meta.get_field('author').formfield().widget,
Book._meta.get_field('author').rel,
my_admin_site,
can_add_related=True
)
)
class Meta:
model = Book
注意事项:
- 您需要确保模板中包含以下两个 javascript 文件:
admin/js/core.js
和admin/js/admin/RelatedObjectLookups.js
.
陷阱:
is_popup
需要在您的模板中正确设置和传递.具体来说,在您覆盖的任何自定义change_form.html
模板中,您必须记住在表单标签中的某处添加此行:{% if is_popup %}<input type="hidden" name="_popup" value="1"/>{% endif %}
,这样BaseModelAdmin.response_add()
返回正确的响应.
is_popup
needs to be set and passed correctly in your templates. Specifically, in any customchange_form.html
templates you override, you must remember to add this line somewhere within your form tags:{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
, so that the logic inBaseModelAdmin.response_add()
returns the correct response.
幕后:本质上,我们正在重用 Django admin 中已经包含的表单处理逻辑、小部件包装器和 javascript.
Under The Hood: Essentially, we're re-using the form processing logic, widget wrapper and javascript that is already included with Django admin.
- 使用
RelatedFieldWidgetWrapper
在我们的表单中包装关联到相关对象字段的小部件(并特别在构造函数中传递can_add_related=True
)告诉小部件附加必要的带有相应 javascript onclick 事件的+"链接. - Django 管理员的 javascript 处理启动弹出窗口所需的所有逻辑.
- 我们的
change_form.html
模板中的{% if is_popup %}...{% endif %}
逻辑和BaseModelAdmin 中的逻辑.response_add()
处理新相关对象的保存并返回适当的 javascript 响应,通知弹出窗口它需要关闭.
- Using
RelatedFieldWidgetWrapper
to wrap the widget associated to the related object field in our form (and specifically passingcan_add_related=True
in the constructor) tells the widget to append the necessary '+' link with the appropriate javascript onclick event attached to it. - Django admin's javascript handles all of the logic necessary to launch the pop-up.
- The
{% if is_popup %}...{% endif %}
logic in ourchange_form.html
template(s) and the logic inBaseModelAdmin.response_add()
handles the saving of the new related object and returns the appropriate javascript response that informs the pop-up that it needs to be closed.
相关回购:这个公共 repo 应该为上面讨论的 Django 项目提供示例代码:https://github.com/cooncesean/Books一个>
Related Repo: This public repo should provide sample code for the Django project discussed above: https://github.com/cooncesean/Books
相关文章