基于Django的Blog 9.使用Form表单类发表新文章

使用Form表单类发表新文章

万一有别的普通用户也要发表文章怎么办?万一我想拓展些后台中没有的提交验证功能又怎么办?

1. 创建Forms表单类

article/forms.py

# 引入表单类
from django import forms
# 引入 文章模型
from . models import ArticlePost


# 写文章的表单类
class ArticlePostForm(forms.ModelForm):
    class Meta:
        # 指明数据模型来源
        model = ArticlePost
        # 定义表单包含的字段
        fields = ('title', 'body')


代码中ArticlePostForm类继承了Django的表单类forms.ModelForm,并在类中定义了内部类class Meta(之前提到过,还记得吗),指明了数据模型的来源,以及表单中应该包含数据模型的哪些字段。

ArticlePost模型中,createdupdated字段为自动生成,不需要填入;author字段暂时固定为id=1的管理员用户,也不用填入;剩下的titlebody就是表单需要填入的内容了。

2. 在视图views中定义业务逻辑

article/views.py

...

# 引入redirect重定向模块
from django.shortcuts import render, redirect
# 引入HttpResponse
from django.http import HttpResponse
# 引入刚才定义的ArticlePostForm表单类
from .forms import ArticlePostForm
# 引入User模型
from django.contrib.auth.models import User

...

# 写文章的视图
def article_create(request):
    # 判断用户是否提交数据
    if request.method == "POST":
        # 将表格中的data数据赋值到表单实例中
        article_post_form = ArticlePostForm(data=request.POST)
        # 提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 满足要求,保存但不提交到数据库
            new_article = article_post_form.save(commit=False)
            # 指定数据库中 id=1 的用户为作者
            # 如果你进行过删除数据表的操作, 可能会找不到id=1的用户
            # 此时请重新创建用户, 并传入此用户的id
            new_article.author = User.objects.get(id=1)
            # 将新文章保存到数据库中
            new_article.save()
            # 完成后返回文章列表
            return redirect("article:article_list")
        # 如果数据不合法
        else:
            return HttpResponse("表单内容有误, 请重新填写.")
    # 如果用户请求的数据方法不是POST
    else:
        # 创建表单类实例
        article_post_form = ArticlePostForm()
        # 赋值上下文
        context = { 'article_post_form': article_post_form }
        # 返回模板
        return render(request, 'article/create.html', context)

首先,当视图函数接收到一个客户端的requset请求时, 首先根据request.method判断用户是要POST提交还是GET获取数据

  • 如果用户是提交数据,将POST给服务器的表单数据赋给ArticlePostForm的实例.然后使用Django内置的is_valid()方法,判断是否符合模型的要求?
  • 如果满足要求,保存表单中的数据(但是commit=False暂时不提交到数据库,因为author还未指定),然后指定author为id=1的管理员用户.然后提交到数据库(save),并redirect返回文章列表,redirect可通过url地址的名字,反向解析到对应的url。
  • 如果不满足要求,则返回一个字符串"表单内容有误, 请重新填写."告诉用户出现了问题
  • 如果用户是获取数据, 则返回一个空的表单类对象, 提供给用户填写

Django官方文档对Form类做了详细的说明:

Form实例可以绑定到数据,也可以不绑定数据。

  • 如果绑定到数据,就能够验证该数据并将表单呈现为HTML并显示数据。
  • 如果它未绑定,则无法进行验证(因为没有要验证的数据!),但仍然可以将空白表单呈现为HTML。

要将数据绑定到表单,就将数据作为字典作为第一个参数传递给Form类构造函数:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data)

Form对象的主要任务是验证数据。使用绑定后的 Form实例,调用is_valid()方法验证并返回指定数据是否有效的布尔值:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True

让我们尝试一些无效的数据。subject为空(错误,因为默认情况下需要所有字段),并且sender不是有效的电子邮件地址:

>> data = {'subject': '',
...         'message': 'Hi there',
...         'sender': 'invalid email address',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
False

关于Forms类的详细解释看这里:The Forms API

这里特别提醒Django中的缩进不能够空格和tab键混用,否则会报错。由于不同的编辑器对tab的显示不尽相同,因此你应该坚持使用空格键缩进。

好视图之后,就需要写模板文件了。在templates/article/中创建create.html

3. 创建对应新文章的模板

templates/article/create.html

{% extends "base.html" %} {% load staticfiles %}
{% block title %} 写文章 {% endblock title %}
{% block content %}
<!-- 写文章表单 -->
<div class="container">
    <div class="row">
        <div class="col-12">
            <br>
            <!-- 提交文章的表单 -->
            <form method="post" action=",">
                <!-- Django中需要POST数据的地方必须有csrf_token -->
                {% csrf_token %}
                <!-- 文章标题 -->
                <div class="form-group">
                    <!-- 标签 -->
                    <label for="title">文章标题</label>
                    <!-- 文本框 -->
                    <input type="text" class="form-control" id="title" name="title">
                </div>
                <!-- 文章正文 -->
                <div class="form-group">
                    <label for="body">文章正文</label>
                    <!--文本区域 -->
                    <textarea type="text" class="form-control" id="body" name="body" rows="12"></textarea>
                </div>
                <!-- 提交按钮-->
                <button type="submit" class="btn brn-primary">完成</button>
            </form>
        </div>
    </div>
</div>
{% endblock content %}

  • < form >...就是表单的整个区域, method="post"制定了表单提交的方式为POST(与视图函数中的request.method相联系);action="."制定了表单提交的地址为默认的当前url

  • {% csrf_token %} 是Django中一个与网络安全相关的中间件验证.目前我们暂时不去深究它的实现,只需要知道表单中必须包含它就可以了,否则将会得到一个403错误。

posted on 2020-07-05 21:03  sunnywillow  阅读(79)  评论(0)    收藏  举报