资讯专栏INFORMATION COLUMN

Django搭建个人博客:使用Form表单类发表新文章

Java3y / 1629人阅读

摘要:一些表单界面元素文本框或复选框非常简单并内置在中,而其他会复杂些像弹出日期选择等操作控件。和标签中的属性指定了当前文本框提交的数据的名称,它必须与表单类中的字段名称对应,否则服务器无法将字段和数据正确的对应起来。

前面我们已经学会如何用Markdown语法书写文章了。

但是还有问题呀。之前写文章都是在后台中进行的,万一有别的普通用户也要发表文章怎么办?万一我想拓展些后台中没有的提交验证功能又怎么办?

本章即讲述如何在前台中提交新的文章,以便满足开发者各种各样的特殊需求

Forms表单类

在HTML中,表单是在

... 中的一些元素
,它允许访客做类似输入文本、选择选项、操作对象或空间等动作,然后发送这些信息到服务端。一些表单界面元素(文本框或复选框)非常简单并内置在HTML中,而其他会复杂些:像弹出日期选择等操作控件。

处理表单是一件挺复杂的事情。想想看Django的admin,许多不同类型的数据可能需要在一张表单中准备显示,渲染成HTML,使用方便的界面进行编辑,传到服务器,验证和清理数据,然后保存或跳过进行下一步处理。

Django的表单功能可以简化上述工作的大部分内容,并且也能比大多数程序员自己编写代码去实现来的更安全。

Django表单系统的核心组件是 Form,它能够描述一张表单并决定它如何工作及呈现。

要使用Form类也很简单,需要在article/中创建forms.py文件,并写入如下代码:

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就是表单需要填入的内容了。

接下来,改写article/views.py,添加一个视图函数以处理写文章的请求:

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":
        # 将提交的数据赋值到表单实例中
        article_post_form = ArticlePostForm(data=request.POST)
        # 判断提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 保存数据,但暂时不提交到数据库中
            new_article = article_post_form.save(commit=False)
            # 指定数据库中 id=1 的用户为作者
            new_article.author = User.objects.get(id=1)
            # 将新文章保存到数据库中
            new_article.save()
            # 完成后返回到文章列表
            return redirect("article:article_list")
        # 如果数据不合法,返回错误信息
        else:
            return HttpResponse("表单内容有误,请重新填写。")
    # 如果用户请求获取数据
    else:
        # 创建表单类实例
        article_post_form = ArticlePostForm()
        # 赋值上下文
        context = { "article_post_form": article_post_form }
        # 返回模板
        return render(request, "article/create.html", context)

分析一下上面的代码。当视图函数接收到一个客户端的request请求时,首先根据request.method判断用户是要提交数据(POST)、还是要获取数据(GET)

如果用户是提交数据,将POST给服务器的表单数据赋于article_post_form实例。

然后使用Django内置的方法.is_valid()判断提交的数据是否满足模型的要求。

如果满足要求,保存表单中的数据(但是commit=False暂时不提交到数据库,因为author还未指定),并指定author为id=1的管理员用户。然后提交到数据库,并通过redirect返回文章列表。redirect可通过url地址的名字,反向解析到对应的url。

如果不满足要求,则返回一个字符串"表单内容有误,请重新填写。",告诉用户出现了什么问题。

如果用户是获取数据,则返回一个空的表单类对象,提供给用户填写。

其实逻辑并不复杂,不明白的读者请逐句理解。

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

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

templates/article/create.html


{% extends "base.html" %} {% load staticfiles %}

{% block title %} 写文章 {% endblock title %}

{% block content %}


{% csrf_token %}
{% endblock content %}

html文件还是一如既往的长。再重复一次,看不懂html文件语法也没有关系,先照着抄一遍,以后再慢慢理解,不影响目前Django的学习。

对其中的新内容进行审视:

..
标签中的内容就是需要提交的表单。method="post"指定了表单提交的方式为POST(与视图函数中的request.method相联系);action="."指定了表单提交的地址为默认的当前url。

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