美文网首页
2.1 通过邮箱分享帖子

2.1 通过邮箱分享帖子

作者: gznb | 来源:发表于2020-07-20 16:40 被阅读0次

    通过邮箱分享贴子

    首先,让我们允许用户通过电子邮件来分享帖子。请花一点时间思考,如何使用在上一节学到的 views.py, URLstemplates 去创建这个功能。为了能允许你的用户使用邮箱分享帖子,你需要做下面的这些事情:

    • 创建一个表单,供用户填写它们的名字,电子邮件,邮件收件人,以及可选的评论。
    • views.py 文件中创建一个视图,它用于处理 post 数据,并且发送邮件。
    • 在blog应用程序的urls.py文件中为新视图添加一个URL模式
    • 创建一个模板来显示表单

    1. 使用 Django 创建表单

    让我们开始创建表单去分享帖子。 Django 有一个内置的 表单 矿建,它允许你使用简单的方式创建表单,定制它如何显示以及验证它输入的数据。Django 表单框架提供了一个灵活的方式去渲染表单和处理数据。

    Django 附带了两个基本类去创建表单:

    • Form: 允许你创建标准的表单。
    • ModelForm: 允许你构建绑定到模型实例的表单。

    首先,在你的 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)
    
    

    这是你的第一个 Django 表单。来看一下这个代码,你通过继承 Form 基础类创建了一个表单。Django 使用不同的字段类型去验证相应的字段。

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

    name 字段是 CharField。 这个类型的字段被渲染为一个 <input type="text"> HTML 节点。每一个字段类型有一个默认的部件,它决定了如何把这个字段渲染到 HTML 中。 通过 widget 属性去覆盖默认的部件。在comments 字段中,使用了一个 Textarea 部件去让它作为 <textarea> HTML 节点代替默认的 <input>节点显示。

    字段验证还取决于字段的类型。例如,emailto 字段 就是 EmailField 字段。这两个字段都必须是一个可发的 email 地址,否则将抛出一个 forms.ValidationError 异常,并且让这个表单无效。表单验证也会去考虑其他的参数: 你在 name 字段上定义了一个最大长度 (maximum) 为 25 个字符。并且用 required=Falsecomments 字段变为可选,所有这些都要考虑到字段验证。在这个表单中使用的字段类型仅仅是Django 表单字段的一部分。所有的字段验证在这个字段中,看这个链接

    2. 在视图中处理表单

    你需要创建一个视图,在数据成功提交的时候,去处理表单数据并且发送一个邮件。编辑你的 blog 应用程序中的 views.py 文件,添加以下代码:

    from .forms import EmailPostForm
    
    
    def post_share(request, post_id):
        # 通过 id 检索帖子
        post = get_object_or_404(Post, id=post_id, status = 'published')
        
        if request.method == 'POST':
            # 表单被提交
            form = EmailPostForm(request.POST)
            if form.is_valid():
                # 表单字段通过验证
                cd = form.cleaned_data
                # ....发送邮件
        else:
            form = EmailPostForm()
        return render(request, 'blog/post/share.html', 
                      {'post': post, 'form': form})
    

    视图工作原理如下:

    • 定义了一个以 request 对象和 post_id 变量作为参数的一个 post_share 视图。
    • 使用 get_object_or_404() 快捷方式通过 ID 检索帖子,并且确保 检索到的帖子具有 published 状态。
    • 可以使用相同的视图来显示初始表单和处理提交的数据。你可以根据 request 方法区分是否提交了表单,并使用 POST提交数据。假设收到一个 GET 请求,就显示一个空表单,如果收到了一个 POST 请求,则提交该表单并且需要处理。因此,你需要使用request.method == 'POST' 去区分这两种情况。

    表单的显示和处理流程如下:

    1. 在最初使用GET请求加载视图时, 你创建了一个 新的表单实例,它被用来在模板种显示一个新的表单。
      form = EmailPostForm()
    2. 用户填写完表单,并且通过 POST 进行提交。这是,你使用包含在 request.POST中提交的数据,创建了一个表单实例。
    if request.method == 'POST':
        # 表单被提交
      form = EmailPostForm(request.POST)
    
    1. 之后,你使用 is_valid() 方法验证提交的数据。此方法验证表单中引入的数据,如果所有字段都包含有效数据,则返回 True。如果任何一个字段包含无效数据,这时 is_valid() 返回 False。你可以通过访问 form.errors 查看验证错误列表。
    2. 如果表单不是有效的,则使用提交的数据在模板中再次呈现表单。你将显示验证错误到模板中。
    3. 如果表单是有效的,通过访问form.cleaned_data来检索经过验证的数据。这个属性是包含表单字段和它们值得字段。

    如果表单数据没有通过验证,cleaned_data 将仅仅包含有效字段。

    现在,让我们探索如何使用Django发送邮件来将所有内容组合在一起。

    3. 使用Django 发送邮件

    使用 Django 发送邮件时很简单的。首先,你需要有一个本地的 SMTP(Simple mail Transfer Protocol) 服务器,或者通过在项目的 settings.py 文件中添加以下设置来定义外部 SMTP 服务器的配置:

    • EMAIL_HOST: SMTP 服务器地址,默认为 localhost
    • EMAIL_PORT: SMTP 服务器端口,默认为 25
    • EMAIL_HOST_USER: SMTP 服务器的用户名。
    • EMAIL_HOST_PASSWORD: SMTP 服务器的密码。
    • EMAIL_USE_TLS: 是否使用一个 Transport Layer Security (TLS) 安全连接。
    • EMAIL_USE_SSL: 是否使用一个 隐式的 TLS 安全连接。

    如果你不能使用 SMTP 服务器,你可以通过在 setting.py 文件中添加以下设置来告诉 Django 向控制台写入电子邮件:
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    通过使用这个配置,Django 将把所有的 emails 输出到 shell 中,这在你的应用中没有 SMTP 服务器测试时是很有用的。

    如果你想要发送邮件,但是你没有本地 SMTP 服务器,你可以使用 email 服务提供者提供的 SMTP 服务。以下实例配置使用一个 Google 账号 通过 Gmail 服务器发送邮件是有效的。

    EMAIL_HOST = ' smtp.gmail.com'
    EMAIL_HOST_USER = ' your_account@gmail.com'
    EMAIL_HOST_PASSWORD = ' your_password'
    EMAIL_PORT = 587
    EMAIL_USE_TLS = True
    

    打开 python shell 运行 python manage.py shell,并且发送邮件,如下:

    image.png

    (译者注: 这里是使用的 EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend')

    image.png

    (译者注: 这里我是配置了一个 163 的邮箱服务器,对比可以看到,两者还是有一点点区别的。)

    send_mail() 函数接受 subject, message, sender, 和 recipients 列表作为所需的参数。通过设置 可选参数fail_silently = False, 告诉它如果邮件没有发送正常, 就抛出一个异常。如果你看到输出 1, 这时邮件就是发送成功了。

    如果你是用前面的配置使用 Gmail 发送邮件,你将不得不启用访问不太安全的应用程序,https://myaccount.google.com/lesssecureapps, 如下:

    image.png
    (译者注: 这里我没有 Google 账号 具体操作一遍。其实用国内的QQ邮箱,163邮箱,可能方便一点)

    在这个例子中,你使用 Django 发送邮件可能还要禁用 Gamil 的验证码。

    编辑在 blog 应用程序里面 views.py 中的 post_share 视图,如下所示:

    from django.core.mail import send_mail
    
    
    def post_share(request, post_id):
        # 通过 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 = f"{cd['name']} recommends you read {post.title}"
                message = f"Read {post.title} at {post_url} \n\n {cd['name']}\'s comments: {cd['comments']}"
                send_mail(subject, message, 'gznbgznb@163.com', [cd['to']])
                sent = True
        else:
            form = EmailPostForm()
        return render(request, 'blog/post/share.html',
                      {'post': post, 'form': form, 'sent': sent})
    

    如果你使用 SMTP 邮件服务器,而不是 控制台的 EmailBackend,就需要使用 你自己真实的 邮箱账号替换 admin@myblog.com

    上面的代码声明了一个 sent 变量,当 帖子发送出去了以后 就把它设置为 True。 你可以在之后当表单成功提交的时候把成功的消息显示在模板中。

    因为你必须在邮件中包含一个链接,你使用一个 get_absolute_url() 方法获得 帖子的 绝对路径,你使用这个路径作为 requests.build_absolute_uri()的输入去构建一个完整的 URL,其中包含了 HTTP 模式和 主机名。你使用 通过验证了以后并且处理的数据创建邮件的 主题 和消息主题。最后把邮件发送给 表单中的 to 字段发送给邮件地址。

    现在你的视图就已经完成了,记住要为它添加一个 新的 路由模式,打开你的blog 应用程序的 urls.py 文件,并且添加一个 post_share 路由模式,如下:

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

    4. 在模板中渲染表单

    创建表单之后,编写视图,添加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 method="post">
                {{ form.as_p }}
                {% csrf_token %}
                <input type="submit" value="Send e-mail">
            </form>
        {% endif %}
    {% endblock %}
    

    这个模板显示表单,或者当邮件发送成功后显示消息。你们会注意到,你创建了 HTML 表单节点,指明了它不得不以 POST 方式进行提交:
    <form method="post">
    然后在包含实际的表单实例中,你可以告诉Django使用 as_p 方法去字段渲染为HTML 的 <p> 段节点。你也可以通过表单的 as_ul 渲染为无序列表,或者是 as_table 渲染为 HTML 的表格。如果你向去渲染每一个字段,你可以迭代这些字段,{{ form.as_p }} 就像下面的例子:

    {% for field in form %}
        <div>
          {{ field.errors }}
          {{ field.label_tag }} {{ field }}
        </div>
    {% endfor %}
    

    这个{% csrf_token %} 模板标签引入了一个隐藏字段,用来自动生成token 去避免 CSRF(cross-site request forgery) 攻击。这个攻击来自恶意的网站,或者是为站点上的用户执行不需要的操作的程序。你可以在这个链接中发现更多有关的信息。

    前面的那个标签生成了一个隐藏字段就像下面这样:
    <input type='hidden' name='csrfmiddlewaretoken' value='26Jj Ko2lcEtYkGo V9z4XmJIEHLXN5LDR' />

    默认情况下,Django 会从所有的 POST 请求中检查这个 CSRF token。 请记住,在所有通过POST 提交的表单中都要包括 csrf_token 标签。

    编辑 blog/post/detail.html 模板,并且在 {{ post.body | linebreaks }} 变量后面添加 分享帖子的URL。

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

    请记住,您正在使用Django提供的{% url %}模板标记动态地构建URL。你将使用名为 名为 blog 的命名空间和名为 post_share 的 URL,并且通过 帖子 ID 作为参数构建一个 绝对URL。

    现在,使用 python manage.py runserver 启动开发者服务器,并且在你的浏览器中 打开 http://127.0.0.1:8000/blog/。点击任意一个帖子的标题去查看详情页面。在帖子主题下面,你将看到你刚刚添加的链接,如下截图所示:

    image.png

    点击 Share this post, 你应该可以看到这个页面,包含通过 emil 分享帖子的表单,如下所示:

    image.png

    表单的 css 样式包含在示例代码的 static/css/blog.css 文件中。当你点击 **SEND E-MAIL 按钮是,这个表单被提交并且进行检验,如果你的所有表单字段都是合法数据,你就会得到一个成功的消息,如下所示:

    image.png

    如果你输入了无效的数据,表单会被重新渲染,并且包含无效的错误信息,如下:


    image.png

    注意,现代的一些浏览器会阻止你提交带有空的或者错误的文本的表单。这是因为浏览器根据表单字段类型和每个字段的限制进行表单验证。这个例子中,表单没有提交,并且浏览器先为错误的字段显示了错误信息。

    通过邮箱分享帖子已经完成。现在让我们来为你的 blog 创建一个 评论系统。

    相关文章

      网友评论

          本文标题:2.1 通过邮箱分享帖子

          本文链接:https://www.haomeiwen.com/subject/sssykktx.html