Django发送QQ邮件

创建一个表单,供用户填写他们的姓名和电子邮件、电子邮件收件人和可选的注释

创建blog/forms.py

from django import forms

class EmailPostForm(forms.Form):
	name = forms.CharField(max_length=25)
	email = forms.EmailField()
	to = forms.EmailField()
	comments = forms.CharField(required=False,widget=forms.Textarea)
  • name会出现在邮件标题和正文中,是发起分享的人qli➊
  • email是发起分享的人的邮件地址,不是系统发送邮件的地址,只是展示在邮件标题分享人括号中。系统发送邮件地址是写到setting.py中的EMAIL_HOST_USER➋
  • to 是收件人地址➌
  • comments是分享的备注信息,会出现在邮件正文➍

通过继承form基类创建了一个表单。Django使用不同的字段类型来验证字段。
每个字段类型都有一个默认的HTML小部件,name字段为CharField,使用<input type="text"> HTML标签呈现。
使用widget属性可以覆盖默认HTML部件。在comments字段中,使用Textarea部件将用<textarea>标签,而不是默认的<input>标签。

required将comments字段定义为可选字段。

表单字段 | Django 文档 | Django (djangoproject.com)

📌表单可以驻留在Django项目的任何地方。惯例是将它们放在每个应用程序的forms.py文件中。

创建一个视图,用于处理提交的数据并发送电子邮件

from .forms import EmailPostForm
from django.core.mail import send_mail

def post_share(request, post_id):
	post = get_object_or_404(Post, id=post_id, status='published')
	sent = False
	if request.method == 'POST':
		form = EmailPostForm(request.POST)
		if form.is_valid():
			cd = form.cleaned_data
			post_url = request.build_absolute_uri(post.get_absolute_url())
			subject = '{}({}) recommends you reading"{}"'.format(cd['name'],cd['email'],post.title)
			message = 'Read"{}" at {}\n\n{}\'s comments:{}'.format(post.title,post_url,cd['name'],cd['comments'])
			send_mail(subject,message,'admin@blog.com',[cd['to']])
			sent = True
	else:
		form = EmailPostForm()

	template = "blog/post/share.html"
	context = {
		'post':post,
		'form':form,
		'sent':sent,
	}
	return render(request, template,context)
  • 这里定义了post_share视图作为request对象,使用post_id作为请求参数。
  • 使用了get_object_or_404()按id检索文章,并确保检索到的文章为已发布状态。
  • 声明了一个发送变量sent,并在发送邮件时将其设置为True。稍后将在模版中使用该变量,以便在表单成功提交时显示成功信息。
  • 根据请求方法request.method区分表单是否被提交,如果收到get请求,则必须显示一个空表单,如果收到POST请求,则提交表单进行处理。
  • 使用POST请求中的数据创建表单form = EmailPostForm()
  • 使用form.is_valid()验证表单数据,如果所有字段都包含有效数据,返回Ture。
  • 如果表单无效,使用提交的数据在模版中再次呈现表单,并在模版中显示验证错误。
  • 如果表单有效,通过form.cleaned_data检索经过验证的数据,包含表单字段和值的字典。

📌 如果表单验证无效,cleaned_data仅包含表单字段。

由于要在电子邮件中包含指向该文章的链接,因此使用该文章的get_absolute_url()方法检索该文章的绝对路径,作为request.build_absolute_uri()的输入,构建一个完整的URL,包括HTTP和主机名。

  • subject:邮件标题=名字+(+邮件地址+)+ recommends you reading +文章标题➊
  • message:Read + 文章标题+ at +文章URL,换行,姓名+’s comments: + 备注 ➎

使用经过验证的表单数据构建电子邮件的主题和消息体,最后将电子邮件发送到表单的to字段包含的电子邮件地址。

在应用的urls.py中为新视图添加一个URL路径

urlpatterns = [

# ...

path('<int:post_id>/share/',views.post_share, name='post_share'),

]

创建一个模版来显示表单

在创建表单、编程视图和添加URL模式之后,还缺少这个视图的模板。
在blog/templates/blog/post/目录新建一个文件,命名为share.html

{% extends "blog/base.html" %}
{% block title %}Share a post{% endblock %}
{% block content %}
	{% if sent %}
		<h1>E-mail successfully sent</h1>
		<p>
			"{{ post.title }}" was successfully sent to {{ form.cleaned_data.to
			}}.
		</p>
	{% else %}
		<h1>Share "{{ post.title }}" by e-mail</h1>
		<form action="." method="post">
			{{ form.as_p }}
			{% csrf_token %}
			<input type="submit" value="Send e-mail">
		</form>
	{% endif %}
{% endblock %}

使用form.as_p方法会使用\<p>呈现段落,还可以使用as_ul将表单呈现为无序列表,或者使用as_table将表单呈现为HTML表格。
如果需要遍历每个字段,可以使用:

{% for field in form %}

	<div>
	
		{{ field.errors }}
		{{ field.label_tag }} {{ field }}
	
	</div>

{% endfor %}

在博客详情页把post_share的链接添加到模版
blog/post/detail.html

<p>

	<a href='{% url "blog:post_share" post.id %}'>
	Share this post
	</a>

</p>