Django管理后台操作确认页面

13

在我的Django项目中,我有一个需要确认页面的管理员操作。我参考了delete_selected操作,但它不起作用。这是我的代码。

我的admin.py的一部分

def my_action(modeladmin, request, queryset):
    if request.POST.get('post'):
        print "Performing action"
        # action code here
        return None
    else:
        return TemplateResponse(request, "admin/my_action_confirmation.html")

管理员/我的操作确认页面.html

<form action="" method="post">{% csrf_token %}
    <div>
        <input type="hidden" name="post" value="yes" />
        <input type="hidden" name="action" value="my_action" />
        <input type="submit" value="Confirm" />
    </div>
</form>

这基本上是有效的。我可以到达确认页面,但如果我点击“确认”,我只会回到原始页面。动作代码部分永远不会被执行。事实上,我的my_action函数没有第二次被调用。那么,我如何告诉django,在我点击确认后应该再次调用my_action函数?

4个回答

11

编辑:我比想象中更缺失

已更正的my_action

def my_action(modeladmin, request, queryset):
    if request.POST.get('post'):
        print "Performing action"
        # action code here
        return None
    else:
        request.current_app = modeladmin.admin_site.name
        return TemplateResponse(request, "admin/my_action_confirmation.html")

管理员/我的操作确认.html

{% load l10n %}
<form action="" method="post">{% csrf_token %}
    <div>
        {% for obj in queryset %}
        <input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
        {% endfor %}
        <input type="hidden" name="post" value="yes" />
        <input type="hidden" name="action" value="my_action" />
        <input type="submit" value="Confirm" />
    </div>
</form>

1
这个不起作用。这篇文章已经四年了,但如果你能解释一下为什么这对你有用,那就太好了。 - Michael Romrell
@MichaelRomrell:诀窍在于模板中的表单必须至少包含一个带有 name="{{ action_checkbox_name }}"<input>,否则确认提交将被忽略。您可以在 ModelAdmin.changelist_view 的源代码 中看到这一点。请注意,request.current_app 行不是必需的。 - djvg
还可以查看源代码中的delete_selected action和相应的delete_selected_confirmation template - djvg

6

admin.py

def require_confirmation(func):
    def wrapper(modeladmin, request, queryset):
        if request.POST.get("confirmation") is None:
            request.current_app = modeladmin.admin_site.name
            context = {"action": request.POST["action"], "queryset": queryset}
            return TemplateResponse(request, "admin/action_confirmation.html", context)

        return func(modeladmin, request, queryset)

    wrapper.__name__ = func.__name__
    return wrapper

@require_confirmation
def do_dangerous_action(modeladmin, request, queryset):
    return 42/0

admin/action_confirmation.html

{% extends "admin/base_site.html" %}
{% load i18n l10n admin_urls %}

{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation
  delete-selected-confirmation{% endblock %}

{% block content %}
  <p>Are you sure you want to {{ action }}?</p>
  <ul style="padding: 0">
    {% for object in queryset.all %}
      <li style="list-style: none; float: left; margin: 5px">
        {{ object }}
      </li>
    {% endfor %}
  </ul>
  <hr>
  <br>
  <form action="" method="post">{% csrf_token %}
    <fieldset class="module aligned">
      {% for obj in queryset.all %}
        <input type="hidden" name="_selected_action" value="{{ obj.pk|unlocalize }}"/>
      {% endfor %}
    </fieldset>
    <div class="submit-row">
      <input type="hidden" name="action" value="{{ action }}"/>
      <input type="submit" name="confirmation" value="Confirm"/>
      <a href="#" onclick="window.history.back(); return false;"
         class="button cancel-link">{% trans "No, take me back" %}</a>
    </div>
  </form>
{% endblock %}

欢迎来到Stackoverflow。请解释您的代码为什么以及如何解决问题,以便其他人更容易理解。 - octobus
1
我知道这可能只是一个自动消息,让人们帮助策划SO,但每当我看到这个,它总是给人一种典型的SO(B)消极攻击的感觉。 - snakesNbronies

4
这是对我有用的内容:
添加确认操作方法(在admin.py中)
from django.template.response import TemplateResponse

def confirm_my_action(modeladmin, request, queryset):
    response = TemplateResponse(request, 
                                'admin/confirm_my_action.html', 
                                {'queryset': queryset})
    return response

并且从您的管理模型(在admin.py中)指向它。

class SomeModelAdmin(admin.ModelAdmin):
    actions = [confirm_my_action]

添加模板,该模板具有一个表单,其操作指向我的_action端点。
{% extends "admin/base_site.html" %}
{% block content %}
<div id="content" class="colM delete-confirmation">
    <form method="post" action="/admin/my_action/">
        {% csrf_token %}
        <div>
            {% for obj in queryset %}
            <input type="hidden" name="obj_ids[]" value="{{ obj.pk }}" />
            <ul><li>Obj: ">{{obj}}</a></li></ul>
            {% endfor %}
        </div>
        <input type="submit" value="Yes, I'm sure">
        <a href="/admin/app/somemodel/" class="button cancel-link">No, take me back</a>
    </form>    
    <br class="clear">
    <div id="footer"></div>
</div>
{% endblock %}

添加适当的端点(例如在urls.py中)。

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^admin/my_action/', my_action_method),
]

4

如果有人想要将确认视图添加到除了动作以外的其他内容中,以下是提供帮助的方法。

我想要在管理创建视图中添加一个确认视图,我的模型非常复杂,并为系统创建了许多影响。添加确认视图可以确保管理员意识到这些影响。

解决方案是覆盖一些 _changeform_view 方法,在创建和编辑时调用。

完整的代码在这里:https://gist.github.com/rsarai/d475c766871f40e52b8b4d1b12dedea2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接