Python 如何在Django Admin中将自定义操作添加到变更模型表单中?
我正在使用Django admin,我希望能够使用模型的现有实例作为模板来创建新对象,因此使用Django admin的用户在创建新对象时不需要重新设置对象上所有相同属性的关键帧 我在Django管理表单的底部描绘了一个类似的场景,用于更新单个对象: django文档解释了如何通过添加到模型上的操作来添加批量操作,如下所示:Python 如何在Django Admin中将自定义操作添加到变更模型表单中?,python,django,django-admin,Python,Django,Django Admin,我正在使用Django admin,我希望能够使用模型的现有实例作为模板来创建新对象,因此使用Django admin的用户在创建新对象时不需要重新设置对象上所有相同属性的关键帧 我在Django管理表单的底部描绘了一个类似的场景,用于更新单个对象: django文档解释了如何通过添加到模型上的操作来添加批量操作,如下所示: class ArticleAdmin(admin.ModelAdmin): actions = ['make_published'] def make
class ArticleAdmin(admin.ModelAdmin):
actions = ['make_published']
def make_published(self, request, queryset):
queryset.update(status='p')
make_published.short_description = "Mark selected stories as published"
然而,对于一个对象上的单个更改模型
表单,对于我一次只想应用于模型的操作,我不太清楚如何做到这一点
我该怎么做
我猜我可能需要用它四处转转,但除此之外,我不太确定
有没有一种快速的方法可以在不覆盖模板加载的情况下完成此操作?Django Admin不提供为更改表单添加自定义操作的方法 然而,你可以通过几次黑客攻击得到你想要的 首先,您必须覆盖提交行 你的应用程序/templates/admin/submit\u line.html
{% load i18n admin_urls %}
<div class="submit-row">
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}
{% if show_delete_link %}
{% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
<p class="deletelink-box"><a href="{% add_preserved_filters delete_url %}" class="deletelink">{% trans "Delete" %}</a></p>
{% endif %}
{% if show_save_and_copy %}<input type="submit" value="{% trans 'Create a new item based on this one' %}" name="_save_and_copy" />{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" />{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" />{% endif %}
</div>
这个例子是针对你的具体情况,如果你需要的话,你可以让它更通用
也就是说,对于您的特定案例,您也可以单击“保存并继续”保存您的工作,然后单击“另存为新”制作副本。是吗?正如所指出的,没有办法,需要被黑客攻击。我认为这是一个优雅的技巧,可以将自定义操作添加到列表视图和更改表单视图中。它实际上并没有保存表单,只是对当前对象执行您想要的任何自定义操作,然后返回到相同的更改表单页面
从django.db.models导入模型
从django.contrib导入管理,消息
从django.contrib.admin.options导入(
不引用,
csrf\u保护\u m,
HttpResponseRedirect,
)
类ArticleAdmin(admin.ModelAdmin):
change\u form\u template='book/admin\u change\u form\u book.html'
操作=['make_published']
def发布(自我、请求、查询集):
如果是实例(查询集,模型):
obj=查询集
对象状态='p'
obj.save()
更新的\u计数=1
其他:
updated_count=queryset.update(status='p')
msg=“已标记{}现有对象中的新对象”。格式(更新的\u计数)
self.message\u用户(请求、消息、消息.成功)
make_published.short_description=“将选定的故事标记为已发布”
@保护
def changeform_视图(self、request、object_id=None、form_url=''、extra_context=None):
如果request.method==“POST”和“request.POST”中的“\u make\u published”:
obj=self.get_对象(请求,取消引用(对象id))
自我发布(请求,obj)
返回HttpResponseRedirect(request.get_full_path())
返回admin.ModelAdmin.changeform\u视图(
自我,请求,
object\u id=object\u id,
form_url=form_url,
额外上下文=额外上下文,
)
现在,您可以为自定义模板视图中的操作添加一个
(本例在change\u form\u模板中使用book/admin\u change\u form\u book.html
)
{%extends'admin/change\u form.html%}
{%block form_top%}
{%endblock%}
如果查看admin/change\u form.html
(即“django/contrib/admin/templates/admin/change\u form.html”),可以在页面上的
标记之间的任意位置插入此自定义
操作。包括这些区块:
{%block form\u top%}
{%block after\u related\u objects%}
{%block submit\u按钮\u bottom%}
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
class ArticleAdmin(admin.ModelAdmin):
def render_change_form(self, request, context, *args, **kwargs):
"""We need to update the context to show the button."""
context.update({'show_save_and_copy': True})
return super().render_change_form(request, context, *args, **kwargs)
def response_post_save_change(self, request, obj):
"""This method is called by `self.changeform_view()` when the form
was submitted successfully and should return an HttpResponse.
"""
# Check that you clicked the button `_save_and_copy`
if '_save_and_copy' in request.POST:
# Create a copy of your object
# Assuming you have a method `create_from_existing()` in your manager
new_obj = self.model.objects.create_from_existing(obj)
# Get its admin url
opts = self.model._meta
info = self.admin_site, opts.app_label, opts.model_name
route = '{}:{}_{}_change'.format(*info)
post_url = reverse(route, args=(new_obj.pk,))
# And redirect
return HttpResponseRedirect(post_url)
else:
# Otherwise, use default behavior
return super().response_post_save_change(request, obj)