美文网首页
使用表单

使用表单

作者: 蝉时雨丶 | 来源:发表于2020-06-19 10:32 被阅读0次

除非您计划搭建的网站和应用只发布内容且不接收访问者的输入,否则您就需要理解和使用表单。

Django提供了一系列的工具和库来帮助您构建表单来接收网站访客的输入,然后处理以及响应这些输入。

HTML表单

在HTML中,表单是在 <form>...</form> 中的一些元素,它允许访客做一些类似输入文本、选择选项、操作对象或空间等动作,然后发送这些信息到服务端。

一些表单界面元素(文本框或复选框)内置在HTML中。其他会更复杂些;像弹出日期选择或者允许您移动滑块或者操作控件,一般通过使用JavaScript,CSS以及HTML表单中的 <input> 元素来实现这些效果。

和它的元素 <input> 一样,表单必须指定两样东西:

  • 何地:负责响应用户输入数据的URL地址
  • 如何:数据请求使用的HTTP方法。

例如,Django admin的登录表单包含了一些 <input> 元素:用户名用 type="text" ,密码用 type="password" ,登录按钮用 type="submit" 。它还包含一些用户看不到的隐藏文本字段,Django用它们来决定下一步行为。

它还告诉浏览器表单数据应该发往 <form> 的 action 属性指定的URL—— /admin/ ,并且应该使用它的 method 属性指定的HTTP方法—— post 。

当 <input type="submit" value="Log in"> 元素被触发的时候,数据会发送到 /admin/ 。

GET 和 POST

处理表单时只会用到 GET 和 POST 两种HTTP方法。

Django的登录表单使用 POST 方法传输数据,在这个方法中浏览器会封装表单数据,为了传输会进行编码,然后发送到服务端并接收它的响应。

相比之下,GET 方法将提交的数据捆绑到一个字符串中,并用它来组成一个URL。该URL包含了数据要发送的地址以及一些键值对应的数据。如果您在Django文档中进行一次搜索,就会看到这点,它会生成一个形似 https://docs.djangoproject.com/search/?q=forms&release=1 的URL。

GET 和 POST 通常用于不同的目的。

任何可能用于更改系统状态的请求应该使用 POST —— 比如一个更改数据库的请求。GET 应该只被用于不会影响系统状态的请求。

GET 方法也不适合密码表单,因为密码会出现在URL中,于是也会出现在浏览器的历史记录以及服务器的日志中,而且都是以纯文本的形式。它也不适合处理大量的数据或者二进制数据,比如一张图片。在WEB应用的管理表单中使用 GET 请求具有安全隐患:攻击者很容易通过模拟请求来访问系统的敏感数据。 POST 方法通过与其他像Django的 CSRF protection 这样的保护措施配合使用,能对访问提供更多的控制。

另一方面, GET 方法适用于诸如网页搜索表单这样的内容,因为这类呈现为一个 GET 请求的URL很容易被存为书签、分享或重新提交。

Django在表单中的角色

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

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

Django会处理涉及表单的三个不同部分:

  • 准备并重组数据,以便下一步的渲染
  • 为数据创建HTML 表单
  • 接收并处理客户端提交的表单及数据

您 可以 手动编写代码来实现,但Django 可以帮你完成所有这些工作。

Django 中的表单

我们已经简单的描述过了HTML 表单,但是一个HTML <form> 只是其所需的一部分。

Web应用中所说的'表单',可能指的是HTML <form> ,或者是生成了它的Django Form ,再或者是提交时返回的结构化数据,亦或是这些端到端作业的合集。

Django的 Form

Django表单系统的核心组件是 Form 类。它与Django模型描述对象的逻辑结构、行为以及它呈现给我们内容的形式的方式大致相同, Form 类描述一张表单并决定它如何工作及呈现。

类似于模型类的字段映射到数据库字段的方式,表单类的字段会映射到HTML表单的 <input> 元素。 ModelForm 通过 Form 映射模型类的字段到HTML表单的 <input> 元素,Django admin就基于此。

表单字段本身也是类;他们管理表单数据并在提交表单时执行验证。 DateFieldFileField 处理的数据类型差别很大,所以必须用来处理不同的字段。

在浏览器中,表单字段以HTML“控件”(用户界面的一个片段)的形式展现给我们。每个字段类型都有与之相匹配的 控件类 ,但必要时可以覆盖。

实例化、处理和渲染表单

在Django中渲染一个对象的时候,我们通常:

1.在视图中获取它(例如从数据库中取出)
2.将它传递给模板上下文
3.使用模板变量将它扩展为HTML标记
在模板中渲染表单几乎与渲染任何其他类型的对象的一样,但是存在一些关键性的差异。

如果模型实例不包含数据,在模板中对它做任何处理几乎没什么用。但完全有理由用来渲染一张空表单——当我们希望用户来填充的时候就会这么做。

所以当我们在视图中处理模型实例时,我们一般从数据库中获取它。当我们处理表单时,我们一般在视图中实例化它。

当我们实例化表单时,我们可以选择让它为空或者对它预先填充,例如使用:

来自已保存的模型实例的数据(例如在管理编辑表单的情况下)
我们从其他来源获取的数据
从前面一个HTML 表单提交过来的数据
最后一种情况最有趣,因为这使得用户不仅可以阅读网站,而且还可以将信息发回给它。

构建一张表单

需要完成的工作

假设您希望在您的网站上创建一张简易的表单,用来获取用户的名字。您需要在模板中使用类似代码:

<form action="/your-name/" method="post">
    <label for="your_name">Your name: </label>
    <input id="your_name" type="text" name="your_name" value="{{ current_name }}">
    <input type="submit" value="OK">
</form>

这告诉浏览器将表单数据返回给URL /your-name/ ,并使用 POST 方法。它将显示一个标签为 "Your name:" 的文本字段,以及一个 "OK" 按钮。如果模板上下文包含一个 current_name 变量,它会被预填充到 your_name 字段。

您需要一个视图来渲染这个包含HTML表单的模板,并能适当提供 current_name 字段。

提交表单时,发送给服务器的 POST 请求将包含表单数据。

现在,您还需要一个与该 /your-name/ URL相对应的视图,该视图将在请求中找到相应的键/值对,然后对其进行处理。

这是一张非常简单的表单。实际应用中,一张表单可能包含数十上百的字段,其中许多可能需要预填充,并且我们可能希望用户在结束操作前需要多次来回编辑-提交。

我们可能需要在浏览器中进行一些验证,甚至在表单提交之前;我们可能希望使用更复杂的字段 ,以允许用户做类似日期选择等操作。

此刻,我们很容易通过使用Django来完成以上大部分工作。

在Django 中构建一张表单

Form

我们已经很清楚想要的HTML表单看起来会是什么样子。首先,在Django中这样做:

forms.py

from django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label='Your name', max_length=100)

它定义了一个只包含一个字段( your_name )的 Form 类。我们已经为这个字段提供了友好的标签,当它渲染后会显示在 <label> 中(在这种情况下,如果我们省略之前指定的 label ,它还是会自动生成一个一样的标签)。

字段的最大长度由 max_length 来定义。它做了两件事情。首先它在HTML的 <input> 上增加了 maxlength="100" (这样浏览器会在第一时间阻止用户输入超过这个数量的字符串)。其次它还会在Django收到浏览器传过来的表单时,对数据长度进行验证(也就是服务器端验证)。

A Form instance has an is_valid() method, which runs validation routines for all its fields. When this method is called, if all fields contain valid data, it will:

  • 返回 True
  • 将表单的数据放到它的属性 cleaned_data 中。

这样整个表单在第一次渲染时,会显示如下:

<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100" required>

注意它 没有 包含 <form> 标签和提交按钮。我们必须自己在模板中提供。

视图

发回Django网站的表单数据由视图来处理,一般和发布这个表单用的是同一个视图。这允许我们重用一些相同的逻辑。

为了处理表单,我们需要将它实例化到我们希望发布的URL的对应的视图中:
views.py

from django.http import HttpResponseRedirect
from django.shortcuts import render

from .forms import NameForm

def get_name(request):
    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = NameForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            # ...
            # redirect to a new URL:
            return HttpResponseRedirect('/thanks/')

    # if a GET (or any other method) we'll create a blank form
    else:
        form = NameForm()

    return render(request, 'name.html', {'form': form})

模板

我们没有必要在模板 name.html 中做过多的操作:

<form action="/your-name/" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="Submit">
</form>

所有的表单字段及其属性都将通过Django模板语言从 {{ form }} 中被解包成HTML标记。

所有的表单字段及其属性都将通过Django模板语言从 {{ form }} 中被解包成HTML标记。

  • 表格和跨站请求伪造保护

Django自带一个简单易用的 跨站请求伪造防护 。当通过 POST 方法提交一张启用了CSRF防护的表单时,您必须使用上例中这样的模板标签 csrf_token 。但是,由于CSRF防护在模板中没有与表单直接绑定,因此这个标签在本页文档之后的示例中都将被忽略。

*HTML5输入类型和浏览器验证

如果您的表单包含 URLFieldEmailField 或者其他整数字段类型,Django将使用 urlemailnumber HTML5输入类型。默认情况下,浏览器可能会在这些字段上应用他们自己的验证,这也许比Django的验证更加严格。如果您想禁用这个行为,请在 form 标签上设置 novalidate 属性,或者在字段上指定一个不同的控件,比如 TextInput

现在我们有了一个可以工作的web表单,它通过一张Django Form 描述,由一个视图来处理并渲染成一个HTML <form>

以上是您入门需要了解的所有内容,但是表单框架提供了更多垂手可得的内容。一旦您理解了上述过程的基础知识,您应该再了解下表单系统的其他功能,然后学习更多的底层机制。

详解Django Form

模型和表单

实际上,如果您的表单是要直接用来添加或编辑Django模型,用 ModelForm ,可以省时、省力、省代码,因为它会根据 Model 类构建一张对应字段及其属性的表单。

字段详解

考虑一下比我们上面的小示例更有用的一张表单,我们可以用它在个人网站上实现“联系我”的功能:

forms.py

from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField(widget=forms.Textarea)
    sender = forms.EmailField()
    cc_myself = forms.BooleanField(required=False)

我们之前的表单只用了一个 CharField 类型的字段 your_name 。在这个例子中,我们的表单有四个字段: subjectmessagesendercc_myself 。只用到三种可用的字段类型: CharFieldEmailFieldBooleanField ;完整的字段类型清单请参看 Form fields

控件

每个表单字段都有一个相对应的 控件类 ,这个控件类又有对应的HTML表单控件,比如 <input type="text">

多数情况下,字段都有合适的默认控件。比如,默认情况下, CharField 有个 TextInput 控件,它会在HTML中生成一个 <input type="text"> 。如果您想要的是 <textarea> `` ,您要在定义表单字段的时候指定控件,就像我们对 ``message 字段那样处理。

字段数据

无论用表单提交了什么数据,一旦通过调用 is_valid() 验证成功( is_valid() 返回 True ),已验证的表单数据将被放到 form.cleaned_data 字典中。这里的数据已经很好的为你转化为Python类型。

注解

此时您依然能够直接从 request.POST 中访问到未验证的数据,但最好还是使用经验证的数据。

在上面的联系表单示例中, cc_myself 会被转化成一个布尔值。同样的,字段 IntegerFieldFloatField 的值分别会被转化为Python的 intfloat 类型。

下面例举了如何在视图中处理表单数据:
views.py

from django.core.mail import send_mail

if form.is_valid():
    subject = form.cleaned_data['subject']
    message = form.cleaned_data['message']
    sender = form.cleaned_data['sender']
    cc_myself = form.cleaned_data['cc_myself']

    recipients = ['info@example.com']
    if cc_myself:
        recipients.append(sender)

    send_mail(subject, message, sender, recipients)
    return HttpResponseRedirect('/thanks/')

有些字段类型需要一些额外的处理。例如,使用表单上传文件就要以不同的方式处理(它们可以从 request.FILES 获取,而不是 request.POST 中)。有关如何使用表单处理文件上传的详细信息,请参见 Binding uploaded files to a form

相关文章

  • 关于vue v-decorator

    ant-desigin-vue中form表单的使用 form表单的使用 form表单之获取表单的数据 创建表单 通...

  • 网页设计:HTML表单标签

    表单包含三个基本组成部分:表单标签、表单域、表单按钮。 1,表单标签 HTML 表单用于收集用户输入,表单使用 ...

  • JavaWeb (day5)

    1.表单提交方式 使用 submit 提交 使用 button 提交表单 使用超链接提交 onclick :鼠标点...

  • 二十七. 表单交互与模拟登陆

    表单交互:使用Requests库的POST使用方法,通过观察表单的网页源代码进行表单的提交,最后通过抓包获取表单提...

  • JAVAWeb(第三周)

    表单提交方式 *使用submit提交 .... *使用button提交表单 -代码 //实现提交方法 functi...

  • 表单提交

    表单提交方式 使用submit提交 使用button提交表单 使用超链接提交 onclick:鼠标点击事件onch...

  • 表单

    表单: form 元素创建表单 常用属性: action:提交表单的地址 method:提交表单使用的方法,一般有...

  • hc6(5-1~5-9)

    使用表单标签,与用户交互 网站怎样与用户进行交互?答案是使用HTML表单(form)。表单是可以把浏览者输入的数据...

  • HTML+CSS学习笔记(5)- 与浏览者交互,表单标签

    1、使用表单标签,与用户交互 网站怎样与用户进行交互?答案是使用HTML表单(form)。表单是可以把浏览者输入的...

  • 飞冰组件formbinder获取图片地址绑定

    图片地址上传回显,需要表单提交,官方文档不推荐使用form表单,于是使用formbinder表单粘合剂。图片地址上...

网友评论

      本文标题:使用表单

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