创建一个表单,供用户填写他们的姓名和电子邮件、电子邮件收件人和可选的注释
创建blog/forms.py
python
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文件中。
创建一个视图,用于处理提交的数据并发送电子邮件
python
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路径
python
urlpatterns = [
# ...
path('<int:post_id>/share/',views.post_share, name='post_share'),
]
创建一个模版来显示表单
在创建表单、编程视图和添加URL模式之后,还缺少这个视图的模板。
在blog/templates/blog/post/目录新建一个文件,命名为share.html
python
{% 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表格。
如果需要遍历每个字段,可以使用:
python
{% for field in form %}
<div>
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
在博客详情页把post_share的链接添加到模版
blog/post/detail.html
python
<p>
<a href='{% url "blog:post_share" post.id %}'>
Share this post
</a>
</p>