【问题标题】:Add checkbox and delete actions to customized Django admin change_list向自定义的 Django 管理员 change_list 添加复选框和删除操作
【发布时间】:2018-02-08 19:23:28
【问题描述】:

我一直在自定义Djangochange_list.html 跟随这个tutorial。我的问题涉及该教程未涵盖的内容:

如何轻松添加checkboxactions(删除选中项)?

我查看了管理部分的templatetags(主要是here,但我不明白如何轻松地将删除操作添加到自定义change_list.html模板中的每个项目以及应该添加什么ModelAdmin 类)。

更新:

下面是自定义change_list.html,我正在尝试将项目复选框添加到:

{% extends "admin/change_list.html" %}

{% block content_title %}
    <h1>Title</h1>
{% endblock %}

{% block result_list %}
    <div class="results">
        <table id="result_list">
            <thead>
                ...
            </thead>

            <tbody>
                {% for item in items %}
                    <tr class="{% cycle 'row1' 'row2' %}">
                        ...
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    </div>
{% endblock %}

【问题讨论】:

  • @MauricioCortazar 并不是真正的重复,因为对我来说,当管理部分被覆盖时,我什至不知道在哪里放置视图。
  • 听起来和我之前的answer herethis one 类似。
  • @SancaKembang 感谢您的链接。它似乎类似于我遇到的解决方案。将类方法作为模型字段是否很常见(例如您的解决方案中的process_button())?
  • 您可以发布您的模板吗?本教程只是一个视图而不是一个表单。也许有比覆盖列表块更好的方法......在 django.contrib.admin.options.changelist_view 你能看到所有的“基本”魔法。

标签: python django django-admin


【解决方案1】:

关键是看“sale_summary_change_list.html”中扩展的“admin/change_list.html”模板。它的 result_list 块具有所需的形式。您还必须将输入复选框添加到 admin.py/changelist_view 中返回的查询集。我修改了教程中的代码。如果我们希望能够删除单个项目,我们当然必须放弃对销售额的聚合。

from django.contrib import admin
from django.contrib.admin import ModelAdmin, helpers

from .models import SaleSummary, Category


@admin.register(SaleSummary)
class SaleSummaryAdmin(ModelAdmin):
    change_list_template = 'admin/sale_summary_change_list.html'
    date_hierarchy = 'date'

    def changelist_view(self, request, extra_context=None):
        response = super(SaleSummaryAdmin, self).changelist_view(
            request,
            extra_context=extra_context,
        )
        try:
            qs = response.context_data['cl'].queryset
        except (AttributeError, KeyError):
            return response

        # metrics = {
        #     'total': Count('id'),
        #     'total_sales': Sum('amount'),
        # }
        result_qs = list(qs.values('category__name', 'pk', 'amount').order_by('category__name').all())
        map(lambda r: r.update(
            {'check_box': helpers.checkbox.render(helpers.ACTION_CHECKBOX_NAME, r['pk'])}), result_qs)
        response.context_data['summary'] = list(result_qs)

        return response

这是模板:

{% extends "admin/change_list.html" %}
{% load humanize admin_list%}
{% block content_title %}
    <h1> Sales Summary </h1>
{% endblock %}

{% block result_list %}

          {% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %}
          {% if action_form and actions_on_bottom and cl.show_admin_actions %}{% admin_actions %}{% endif %}
    <div class="results">
        <table>
            <thead>
            <tr>
                <th>
                    <div class="text">
                        <a href="#">Action</a>
                    </div>
                </th>
                <th>
                    <div class="text">
                        <a href="#">Category</a>
                    </div>
                </th>
                <th>
                    <div class="text">
                        <a href="#">Total Sales</a>
                    </div>
                </th>
            </tr>
            </thead>
            <tbody>
            {% for row in summary %}
                <tr class="{% cycle 'row1' 'row2' %}">
                    <td> {{ row.check_box }} </td>
                    <td> {{ row.category__name }} </td>
                    <td> {{ row.amount | intcomma }} </td>

                </tr>
            {% endfor %}
            </tbody>

        </table>
    </div>

{% endblock %}

{% block pagination %}{% endblock %}

在github上查看完整的项目:

https://github.com/SabirAkhadov/django-action-change-list-demo

【讨论】:

  • 当您将 id 作为值注入复选框时,为什么使用 force_text
  • 我猜这是从某个地方复制粘贴,这里实际上不需要 force_text。
  • 您是从哪个文件中复制的?我想将change_list.html 中每个项目的链接添加到编辑页面。我知道有ModelAdmin.list_display_links,但我不确定它是否适用于我的情况(使用自定义管理员)。
  • ModelAdmin 类中有一个 action_checkbox 方法,我不知道如何直接使用,所以我复制了它的主体。
【解决方案2】:

@Sabir Answer 是最好的答案,而这个答案是建立在它之上的。

他使用map 将复选框附加到结果列表的部分可能会在您处理这么多行(比如 1000 行)时产生一些性能问题

我发现: 您可以在前端渲染复选框,并将其传递给元素 pk。

您可以保留相同的管理类,但删除 change_list_view 函数中的map 行,让前端工作。

所以我像这样更改了我的模板

{% extends "admin/change_list.html" %}
{% load humanize admin_list%}
{% block content_title %}
    <h1> Sales Summary </h1>
{% endblock %}

{% block result_list %}

          {% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %}
          {% if action_form and actions_on_bottom and cl.show_admin_actions %}{% admin_actions %}{% endif %}
    <div class="results">
        <table>
            <thead>
            <tr>
                <th>
                    <div class="text">
                        <a href="#">Action</a>
                    </div>
                </th>
                <th>
                    <div class="text">
                        <a href="#">Category</a>
                    </div>
                </th>
                <th>
                    <div class="text">
                        <a href="#">Total Sales</a>
                    </div>
                </th>
            </tr>
            </thead>
            <tbody>
            {% for row in summary %}
                <tr class="{% cycle 'row1' 'row2' %}">
                    <td> <td> <input type="checkbox" name="_selected_action" value={{row.pk}} class="action-select"> </td> </td>
                    <td> {{ row.category__name }} </td>
                    <td> {{ row.amount | intcomma }} </td>

                </tr>
            {% endfor %}
            </tbody>

        </table>
    </div>

{% endblock %}

{% block pagination %}{% endblock %}

【讨论】:

  • 不错的答案,即使使用 Django 3.0 仍然有效
猜你喜欢
  • 2013-01-26
  • 2020-03-04
  • 1970-01-01
  • 2015-01-06
  • 2010-12-06
  • 1970-01-01
  • 2018-07-15
  • 2017-05-03
  • 2019-05-26
相关资源
最近更新 更多