如何在 django admin 中通过操作请求用户输入?

问题描述 投票:0回答:3

在我的代码中,我正在编写一个分组操作,我想询问用户每个组想要多少人,然后用一个警报框进行响应,其中显示根据用户您有 4 个组的内容输入。我如何在 django admin 中执行此操作,如何创建某种弹出窗口来询问他们想要放入一个组中的人数? (我正在努力通过行动来实现这一点)

admin.py:

 Def howmany (modeladmin, request, queryset):
      people = queryset.count()
      amount_per = [the number that the user inputs]
      Amount_of_groups = people/amount_per
django django-models django-admin-filters
3个回答
15
投票

我发现了这里更简单、更好的方法:

您只需要创建一个像这样的操作表单。

from django.contrib.admin.helpers import ActionForm
from django import forms


class XForm(ActionForm):
    x_field = forms.ModelChoiceField(queryset=Status.objects.all(), required=False)

现在,在您的 admin.py 中定义该 XForm

class ConsignmentAdmin(admin.ModelAdmin):

    action_form = XForm
    actions = ['change_status']

    def change_status(modeladmin, request, queryset):
        print(request.POST['x_field'])
        for obj in queryset:
            print(obj)
    change_status.short_description = "Change status according to the field"

8
投票

admin.py 类似于:

class MyAdmin(admin.ModelAdmin):

    def howmany(modeladmin, request, queryset):
        people = queryset.count()
        amount_per = [the number that the user inputs]
        Amount_of_groups = people/amount_per

        if 'apply' in request.POST:
            form = AmountPerForm(request.POST)

            if form.is_valid():
                amount_per = form.cleaned_data['amount_per']
                self.message_user(request, u'You selected - %s' % amount_per)
            return HttpResponseRedirect(request.get_full_path())
        else:
            form = AmountPerForm()

        return render(request, 'admin/amount_per_form.html', {
            'items': queryset.order_by('pk'),
            'form': form,
            'title': u'Your title'
            })

文件“admin/amount_per_form.html”包含类似以下内容:

 {% extends 'admin/base_site.html' %}

 {% block content %}
 <form action="" method="post">
    {% csrf_token %}
    <input type="hidden" name="action" value="howmany" />
    {% for item in items %}
    <input type="hidden" name="_selected_action" value="{{ item.pk }}"/> {# thanks to @David Hopkins for highligting it #}
    {% endfor %}

    {{ form }}
    <p>Apply for:</p>
    <ul>{{ items|unordered_list }}</ul>
    <input type="submit" name="apply" value="Apply" />
 </form>
 {% endblock %}

0
投票

如何创建接受用户输入的 Django 管理操作

管理员操作

Django 管理的基本工作流程简而言之就是“选择一个对象,然后更改它”。这对于大多数用例都很有效。但是,如果您需要一次对许多对象进行相同的更改,则此工作流程可能会非常乏味。

在这些情况下,Django 的管理员允许您编写和注册“操作”——使用在更改列表页面上选择的对象列表来调用的函数。

image of admin action from Django documentation

实现这一点需要三段代码:操作方法、表单和 html 模板。这些片段与四个数据片段联系在一起,即操作方法的名称、在表单和方法之间传递的任意隐藏值(用于标识回发)以及模板和表单类的名称。

1.定义操作方法

在您想要应用操作的对象的 Django ModelAdmin 类中定义一个新的“操作”方法,并使用操作名称将

actions
属性添加到您的模型管理中

  • 确定一个隐藏的输入值,您将使用该值从表单中发出用户的回发信号。 该名称不能与您的操作名称相同。 在下面的示例中,调整
    if "send_email_message" in request.POST:
    行以匹配您的选择,然后记住将其添加到下面步骤 3 中的 HTML 模板中。
@admin.register(MyUser)
class MyUserAdmin(admin.ModelAdmin):

    actions = ["send_email_to_user"]

    @admin.action(description="Send email to user")
    def send_email_to_user(self, request, queryset):
        if "send_email_message" in request.POST:
            recipients = [u.email for u in queryset]
            subject_text = request.POST["subject_text"]
            raw_message_lines = request.POST["message_text"].splitlines()
            message_text = "\n".join(raw_message_lines)

            message_html_io = StringIO()

            for line in raw_message_lines:
                if line and line.strip():
                    message_html_io.write(format_html("<p>{}</p>", line))

            message_html = message_html_io.getvalue()

            email_msg = EmailMultiAlternatives(
                subject=subject_text,
                body=message_text,
                from_email=None,
                to=recipients,
            )
            # HTML message
            email_msg.attach_alternative(
                message_html,
                "text/html",
            )

            success = email_msg.send()

            if success:
                email_send_success = (
                    "Your message was sent to the following users: "
                    + r", ".join([u.email for u in queryset])
                )

                self.message_user(request, email_send_success, messages.SUCCESS)
            else:
                email_send_fail = _("Error - Your message was not sent.")
                self.message_user(request, email_send_fail, messages.ERROR)

            # Return to previous page
            return HttpResponseRedirect(request.get_full_path())

        form = SendUserEmailForm(
            initial={"_selected_action": queryset.values_list("id", flat=True)}
        )

        return render(
            request, "admin/send_email_to_user.html", {"items": queryset, "form": form}
        )
  • 记下您在步骤 3 中创建的模板的路径,并将上面的
    render
    命令调整为正确的路径

2.创建一个表单来捕获用户输入

注意:神奇的

_selected_action
将允许您通过上面显示的
queryset
参数将在Django管理界面中选择的项目传递到您的方法中

class SendUserEmailForm(Form):
    _selected_action = CharField(widget=MultipleHiddenInput)
    subject_text = CharField(
        widget=Textarea(
            {"class": "form-control", "rows": 1, "placeholder": _("email subject")}
        ),
        required=True,
        label="Subject",
    )
    message_text = CharField(
        widget=Textarea(
            {
                "class": "form-control",
                "rows": 15,
                "placeholder": _("email text message"),
            }
        ),
        required=True,
        label="Message",
    )

3.创建一个 html 模板来向用户展示表单

  • 将模板保存在
    templates\admin
  • 在此示例中,我将模板另存为
    templates\admin\send_email_to_user.html
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% load widget_tweaks %}

{% block bodyclass %}{{ block.super }} Email User{% endblock %}
{% block usertools %}{% endblock %}
{% block nav-global %}{% endblock %}
{% block nav-sidebar %}{% endblock %}
{% block content_title %}{% endblock %}
{% block nav-breadcrumbs %}{% endblock %}

{% block content %}
<div class="container">
    <h1 class="text-secondary">
        Send email message to user(s)
    </h1>

    {% with WIDGET_ERROR_CLASS='is-invalid' WIDGET_REQUIRED_CLASS='required' %}
    <form method="post" class="form" enctype="multipart/form-data" novalidate>
        {% csrf_token %}
        <div class="form-group col-md-4">

            {% for field in form %}
            <div class="mb-3">
                {% if not field.is_hidden %}
                <label class="form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
                {% endif %}
                {% render_field field %}
                {% for error in field.errors %}
                <div class="invalid-feedback d-block">{{ error }}</div>
                {% endfor %}
            </div>
            {% endfor %}

            {% if form.errors %}
            <div class="invalid-feedback d-block">
                {% for error in form.non_field_errors %}
                <p>{{ error }}</p>
                {% endfor %}
            </div>
            {% endif %}

        </div>
        <div class="form-group col-md-4">
            <!--  Show the list of selected objects on the previous step  -->
            <p>An email message will be sent to these users:</p>
            <ul>{{ items|unordered_list }}</ul>
        </div>

        <div class="submit-row">
            <!--  Link the action name in hidden params -->
            <input type="hidden" name="action" value="send_email_to_user"/>
            <input class="btn btn-danger" type="submit" name="send_email_message"
                   value='{% translate "Send" %}'
            />
        </div>
    </form>
    {% endwith %}
</div>
{% endblock %}}

  • 调整
    name
    按钮的
    submit
    属性以匹配您在上面步骤 1 中选择的隐藏值。
  • 隐藏的值
    input
    与名称属性的“action”值应与您的管理操作方法的名称相匹配
© www.soinside.com 2019 - 2024. All rights reserved.