我的实现使用 CustomUser 模型。 我正在创建一个 Django 管理操作,它允许我撰写电子邮件并将其发送给多个用户。 网站上的所有内容都表现得好像正在运行一样。 点击发送电子邮件按钮后,我被重定向回管理员,但我没有看到任何控制台输出表明电子邮件已发送,并且 self.message_user 从未被调用并发送给管理员。
电子邮件后端
密码重置可与发送到控制台的重置链接一起使用,因此电子邮件后端正在运行。
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
admin.py
如果请求中“应用”。POST:<-- This line never fires!
class CustomUserAdmin(ExportMixin, UserAdmin):
@admin.action(description="Email selected users")
def send_email_action(self, request, queryset):
print(request.POST)
print(request.POST.getlist("apply"))
input("HALT")
if "apply" in request.POST:
print("apply")
form = EmailForm(request.POST)
if form.is_valid():
print("form valid")
subject = form.cleaned_data["subject"]
message = form.cleaned_data["message"]
recipients = [user.email for user in queryset]
send_mail(subject, message, "[email protected]", recipients)
self.message_user(request, f"{len(recipients)} emails were sent.")
return HttpResponseRedirect(request.get_full_path())
else:
print("no apply")
form = EmailForm()
return render(request, "email/admin_send.html", {"form": form})
forms.py
按预期工作。
class EmailForm(forms.Form):
subject = forms.CharField(max_length=256)
message = forms.CharField(widget=forms.Textarea)
admin_send.html
要么:
Q1:我需要定义当前为空的form action=""吗? 我问这个问题是因为感觉当我单击“发送电子邮件”按钮时,它可能不会再次调用 send_email_action 函数。 如果我需要定义它,我不知道在这里放什么,因为通常它是一个 URL,但我需要它是一个管理操作函数。 我相信这是主要问题,因为如果函数被调用,我应该看到 print(request.POST) 的结果再次打印到控制台,但我没有(即:QueryDict)。
Q2:注意input name="apply"。 send_email_action 函数显然正在寻找此数据,但它不会从表单返回,或者即使返回,我也无法在请求对象中找到它。 我相信这也可能是一个问题,但是只有解决了上面的第一个问题之后才能解决。
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block title %}
Email Users
{% endblock %}
{% block content %}
<br>
<br>
<br>
<h2>Email Users</h2>
<form action="" method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" name="apply" value="Send Email">
</form>
{% endblock content %}
第 1 步)在管理中,我在 CustomUser 表中选择了多个用户,从操作下拉菜单中选择了“向选定的用户发送电子邮件”,然后单击了“GO”:
控制台
<QueryDict: {'csrfmiddlewaretoken': ['zHlbmtRaNIFwrdNmCFxwyiVLi1IaCFKHoJAmZWKttwTMN97gC1JhWSryO9POuaDK'], 'action': ['send_email_action'], 'select_across': ['0'], 'index': ['0'], '_selected_action': ['6', '1', '7', '8']}>
[]
HALT
Step2)我在控制台中按回车键继续,表单显示。 我输入主题和消息。
控制台
no apply
[23/Nov/2024 23:58:25] "POST /admin/app_accounts/customuser/?company=Cisco HTTP/1.1" 200 10317
步骤3)我点击“发送电子邮件”按钮。
控制台
[24/Nov/2024 00:02:07] "POST /admin/app_accounts/customuser/?company=Cisco HTTP/1.1" 200 19098
[24/Nov/2024 00:02:07] "GET /admin/jsi18n/ HTTP/1.1" 200 3342
好的,我想出了如何实现这一点。 对我来说,关键只是意识到 form action="" 实际上需要填充。 用什么? 我不知道如何填充它,让我能够回调我的管理操作函数<-- this was my mental block. DUH! I needed to populate it with a normal view, not an admin action function! I needed to split up these pieces of my code. So I created a URL where form POST data could be sent, figured out how to transparently pass data from my admin action function through the intermediate form to my normal view for post processing (a bit of data conversion), then I built my view using portions of the code from my original admin.py file under if“apply” in request.POST:。 然后我简化了我的管理操作功能。
我唯一无法工作的是返回管理界面的确认消息...请参阅views.py 文件倒数第二行的 # 注释。 出现错误:ModelAdmin.message_user() 缺少 1 个必需的位置参数:“message”。 尽管很明显我提供了该消息。 我无法解释为什么会发生这种情况。
这个解决方案对我来说有点脏,因为数据的透明传递似乎是作为 URL 中的参数传递的,但没有传递任何敏感信息,所以我想这没什么大不了的,而且这从来没有透露给最终用户只要代码正常工作即可。
如果有人读到这篇文章,我希望这会有所帮助。另外,如果您能想到更好、更简单、更有效的方法来处理这个问题,请告诉我! 我对 Django 还很陌生,所以我感觉很好,我能完成这个工作,但我想知道是否有更好的方法。
admin.py
class CustomUserAdmin(ExportMixin, UserAdmin):
resource_class = CustomUserResource
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
actions = ["send_email_action"]
@admin.action(description="Email selected users")
def send_email_action(self, request, queryset):
form = EmailForm()
recipients = "|".join([item.email for item in queryset])
return render(
request,
"email/admin_send.html",
{"form": form, "recipients": recipients},
forms.py
class EmailForm(forms.Form):
subject = forms.CharField(max_length=256)
message = forms.CharField(widget=forms.Textarea)
admin_send.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block title %}
Email Users
{% endblock %}
{% block content %}
<br>
<br>
<br>
<h2>Email Users</h2>
<form action="{% url 'process_email' recipients %}" method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Send Email">
</form>
{% endblock content %}
urls.py
from django.urls import path
from .views import process_email_view
urlpatterns = [
path(
"process_email/<str:recipients>/",
process_email_view,
name="process_email",
),
]
views.py
def process_email_view(request, recipients, modeladmin):
form = EmailForm(request.POST)
if form.is_valid():
subject = form.cleaned_data["subject"]
message = form.cleaned_data["message"]
recipients = recipients.split("|")
for recipient in recipients:
send_mail(subject, message, "[email protected]", [recipient])
# CustomUserAdmin.message_user(request, f"{len(recipients)} emails were sent.")
return HttpResponseRedirect("/admin/app_accounts/customuser/")