在我的代码中,我正在编写一个分组操作,我想询问用户每个组想要多少人,然后用一个警报框进行响应,其中显示根据用户您有 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
我发现了这里更简单、更好的方法:
您只需要创建一个像这样的操作表单。
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"
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 %}
管理员操作
Django 管理的基本工作流程简而言之就是“选择一个对象,然后更改它”。这对于大多数用例都很有效。但是,如果您需要一次对许多对象进行相同的更改,则此工作流程可能会非常乏味。
在这些情况下,Django 的管理员允许您编写和注册“操作”——使用在更改列表页面上选择的对象列表来调用的函数。
实现这一点需要三段代码:操作方法、表单和 html 模板。这些片段与四个数据片段联系在一起,即操作方法的名称、在表单和方法之间传递的任意隐藏值(用于标识回发)以及模板和表单类的名称。
在您想要应用操作的对象的 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}
)
render
命令调整为正确的路径注意:神奇的
_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",
)
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”值应与您的管理操作方法的名称相匹配