Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django:如何在管理表单中的历史记录按钮旁边添加操作按钮-干净?_Python_Django_Django Admin - Fatal编程技术网

Python Django:如何在管理表单中的历史记录按钮旁边添加操作按钮-干净?

Python Django:如何在管理表单中的历史记录按钮旁边添加操作按钮-干净?,python,django,django-admin,Python,Django,Django Admin,在我的锦标赛管理员中,我想添加一个创建比赛结构的按钮,它取决于先前注册的参赛球队s。这是一个涉及单个锦标赛的操作,没有“结果”-它只是对数据库进行一个中等复杂的更新 我将该功能作为一个应用程序来实现,它运行良好,而且似乎是实现该功能的最佳方式。但是,大多数情况下,用户希望从锦标赛页面而不是锦标赛列表执行该操作 答案显示了如何将管理操作表单添加到相关页面,但我不需要下拉列表,其中还包括“删除”操作;一个简单的按钮会更好 问题是关于添加按钮(虽然它是针对列表页面的),但正确的样式仅适用于a href

在我的
锦标赛
管理员中,我想添加一个创建比赛结构的按钮,它取决于先前注册的参赛
球队
s。这是一个涉及单个锦标赛的操作,没有“结果”-它只是对数据库进行一个中等复杂的更新

我将该功能作为一个应用程序来实现,它运行良好,而且似乎是实现该功能的最佳方式。但是,大多数情况下,用户希望从锦标赛页面而不是锦标赛列表执行该操作

答案显示了如何将管理操作表单添加到相关页面,但我不需要下拉列表,其中还包括“删除”操作;一个简单的按钮会更好

问题是关于添加按钮(虽然它是针对列表页面的),但正确的样式仅适用于
a href
标记,而不适用于按钮;我正在执行操作,而不是显示新文档。我希望避免在使用表单提交按钮时重复相关CSS。我还希望避免硬编码操作名称,或者通常重复“管理操作”下拉列表为我推断的内容

因此,我的具体问题是:

  • 什么是使造型正确的最好方法?我必须使用
    a
    标记并通过JavaScript提交,还是有更好的方法
  • 如何最好地使用
    {%admin\u actions%}
    (生成带有下拉列表的表单)复制answer获得的逻辑?也就是说,检索管理操作,使用它们的描述显示它们,等等,但是作为按钮
有关守则如下:

admin.py

# from https://stackoverflow.com/a/20379270/371191
class ActionInChangeFormMixin(object):
    def response_action(self, request, queryset):
        """
        Prefer http referer for redirect
        """
        response = super(ActionInChangeFormMixin, self).response_action(request, queryset)
        if isinstance(response, HttpResponseRedirect):
            response['Location'] = request.META.get('HTTP_REFERER', response.url)
        return response

    def change_view(self, request, object_id, form_url='', extra_context=None):
        actions = self.get_actions(request)
        if actions:
            action_form = self.action_form(auto_id=None)
            action_form.fields['action'].choices = self.get_action_choices(request)
        else:
            action_form = None
        extra_context = extra_context or {}
        extra_context['action_form'] = action_form
        return super(ActionInChangeFormMixin, self).change_view(request, object_id, extra_context=extra_context)


class TournamentAdmin(ActionInChangeFormMixin, admin.ModelAdmin):
    actions = ['setup_matches']

    def setup_matches(self, request, queryset):
        for tournament in queryset:
            try:
                tournament.setup()
            except ValueError as ex:
                messages.error(request, 'Could not update %s: %s'  % (tournament, ex))
            else:
                messages.success(request, 'Updated %s' % (tournament,))

    setup_matches.short_description = 'Setup matches for selected tournaments'
{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}

{% block object-tools-items %}
    <li>
        <form action="{% url opts|admin_urlname:'changelist' %}" method="POST">{% csrf_token %}
            <input type="hidden" name="action" value="setup_matches">
            <input type="hidden" name="_selected_action" value="{{ object_id }}">
            <button value="0" name="index" title="Setup matches for selected tournaments" type="submit">Setup matches</button>
        </form>
    </li>
    {{ block.super }}
{% endblock %}
change\u form.py

# from https://stackoverflow.com/a/20379270/371191
class ActionInChangeFormMixin(object):
    def response_action(self, request, queryset):
        """
        Prefer http referer for redirect
        """
        response = super(ActionInChangeFormMixin, self).response_action(request, queryset)
        if isinstance(response, HttpResponseRedirect):
            response['Location'] = request.META.get('HTTP_REFERER', response.url)
        return response

    def change_view(self, request, object_id, form_url='', extra_context=None):
        actions = self.get_actions(request)
        if actions:
            action_form = self.action_form(auto_id=None)
            action_form.fields['action'].choices = self.get_action_choices(request)
        else:
            action_form = None
        extra_context = extra_context or {}
        extra_context['action_form'] = action_form
        return super(ActionInChangeFormMixin, self).change_view(request, object_id, extra_context=extra_context)


class TournamentAdmin(ActionInChangeFormMixin, admin.ModelAdmin):
    actions = ['setup_matches']

    def setup_matches(self, request, queryset):
        for tournament in queryset:
            try:
                tournament.setup()
            except ValueError as ex:
                messages.error(request, 'Could not update %s: %s'  % (tournament, ex))
            else:
                messages.success(request, 'Updated %s' % (tournament,))

    setup_matches.short_description = 'Setup matches for selected tournaments'
{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}

{% block object-tools-items %}
    <li>
        <form action="{% url opts|admin_urlname:'changelist' %}" method="POST">{% csrf_token %}
            <input type="hidden" name="action" value="setup_matches">
            <input type="hidden" name="_selected_action" value="{{ object_id }}">
            <button value="0" name="index" title="Setup matches for selected tournaments" type="submit">Setup matches</button>
        </form>
    </li>
    {{ block.super }}
{% endblock %}
{%extends“admin/change\u form.html”%}
{%load i18n admin_URL%}
{%block object tools items%}
  • {%csrf_令牌%} 设置匹配
  • {{block.super}} {%endblock%}
    ActionInChangeFormMixin.change\u view()
    中的大多数代码都是专门为下拉列表设置的代码,因此在与上面显示的模板一起使用时是死代码。逻辑发生在这里:

    action_form = self.action_form(auto_id=None)
    action_form.fields['action'].choices = self.get_action_choices(request)
    
    action\u form
    创建实际的表单-我们无论如何都不想渲染它
    get\u action\u choices
    使用元组填充
    ,以用作选项

    为了尽可能灵活,我将引入一个新方法,它只检索我们想要显示的操作。另外,让我们去掉不必要的代码(新代码的灵感来源于
    get\u action\u选项
    ):

    TournamentAdmin
    中,我们可以过滤我们想要看到的动作。在这种情况下,我不想显示批量删除操作的按钮:

    def get_change_actions(self, request):
        result = self.get_actions(request)
        del result['delete_selected']
        return result
    
    change\u form.html
    现在需要一些逻辑来呈现相关按钮:

    {% extends "admin/change_form.html" %}
    {% load i18n admin_urls %}
    
    {% block object-tools-items %}
        {% for action_name, action_description in change_actions %}
        <li>
            <form id="action_{{ action_name }}" action="{% url opts|admin_urlname:'changelist' %}" method="POST">{% csrf_token %}
                <input type="hidden" name="action" value="{{ action_name }}">
                <input type="hidden" name="_selected_action" value="{{ object_id }}">
                <a href="#" onclick="document.getElementById('action_{{ action_name }}').submit(); return false;" title="{{  action_description }}">{{  action_description }}</a>
            </form>
        </li>
        {% endfor %}
        {{ block.super }}
    {% endblock %}
    
    {%extends“admin/change\u form.html”%}
    {%load i18n admin_URL%}
    {%block object tools items%}
    {对于操作\名称,更改\操作%中的操作\描述为%
    
  • {%csrf_令牌%}
  • {%endfor%} {{block.super}} {%endblock%}

    这使用JavaScript提交表单;我认为没有更干净的方法来正确地设计样式。

    您能添加按钮吗?