程序地带

第十三课 Django 表单模型(一)


表单模型(一)

Django的Form表单类与Django模型描述对象的逻辑结构、行为以及它呈现给我们内容的形式的方式大致相同


假设你想从表单接收用户名数据,一般情况下,你需要在HTML中手动编写一个如下的表单元素:


<form action="/student/" method="post">
<label for="name">姓名: </label>
<input id="name" type="text" name="name" value="{{ name }}">
<input type="submit" value="提交">
</form>
1. 编写表单类

我们可以通过Django提供的Form类来生成上面的表单,不再需要手动在HTML中编写


首先,在你当前app内新建一个forms.py文件,然后输入下面的内容:


from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label='name', max_length=100)
所有的表单类都要继承forms.Form类max_length限制最大长度为100。它同时起到两个作用,一是在浏览器页面限制用户输入不可超过100个字符,二是在后端服务器验证用户输入的长度不可超过100

每个Django表单的实例都有一个内置的is_valid()方法,用来验证接收的数据是否合法。如果所有数据都合法,那么该方法将返回True,并将所有的表单数据转存到它的一个叫做cleaned_data的属性中,该属性是一个字典类型数据。


当我们将上面的表单渲染成真正的HTML元素,其内容如下:


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

一定要注意,它不包含<form>标签本身以及提交按钮!!!为什么要这样?方便你自己控制表单动作和CSS,JS以及其它类似bootstrap框架的嵌入!


2. 视图处理

需要在视图中,实例化我们编写好的表单类


# views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import NameForm
def get_name(request):
# 如果form通过POST方法发送数据
if request.method == 'POST':
# 接受request.POST参数,绑定要验证的数据
form = NameForm(request.POST)
# 验证数据是否合法
if form.is_valid():
# 处理form.cleaned_data中的数据
return HttpResponse('hello world
# 如果是通过GET方法请求数据,返回一个空的表单
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
对于GET方法请求页面时,返回空的表单,让用户可以填入数据对于POST方法,接收表单数据,并验证

可以通过表单的is_bound属性可以获知一个表单已经绑定了数据,还是一个空表


3. 模板处理

在Django的模板中,我们只需要按下面处理,就可以得到完整的HTML页面,但是submit按钮需要自己定义:


<form action="/student/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="提交" />
</form>
使用POST的方法时,必须添加{% csrf_token %}标签,用于处理csrf安全机制{{ form }}Django会为你生成其它所有的form标签元素提交按钮需要手动添加!
4. 表单字段

上面的例子中,只有一个用户名输入框,太简单了,实际上有更多的表单元素。看下面的例子:


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)

这个例子就有4个框组了。实际上Django的表单模块为我们内置了许多表单字段,如下所示:


BooleanFieldCharFieldChoiceFieldTypedChoiceFieldDateFieldDateTimeFieldDecimalFieldDurationFieldEmailFieldFileFieldFilePathFieldFloatFieldImageFieldIntegerFieldJSONFieldGenericIPAddressFieldMultipleChoiceFieldTypedMultipleChoiceFieldNullBooleanFieldRegexFieldSlugFieldTimeFieldURLFieldUUIDFieldComboFieldMultiValueFieldSplitDateTimeFieldModelChoiceFieldModelMultipleChoiceField

每一个表单字段类型都对应一种Widget类,每一种Widget类都对应了HMTL语言中的一种input元素类型,比如<input type="text">。需要在HTML中实际使用什么类型的input,就需要在Django的表单字段中选择相应的field。比如要一个<input type="text">,可以选择一个CharField。


一旦你的表单接收数据并验证通过了(is_valid()),那么就可以从form.cleaned_data字典中读取所有的表单数据,并且已经转化为恰当的Python类型。例子:


# 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/')
5. 使用表单模板
① 表单渲染格式

前面我们通过{{ form }}模板语言,简单地将表单渲染到HTML页面中了,实际上,有更多的方式:


{{ form.as_table }} 将表单渲染成一个表格元素,每个输入框作为一个<tr>标签{{ form.as_p }} 将表单的每个输入框包裹在一个<p>标签内 tags{{ form.as_ul }} 将表单渲染成一个列表元素,每个输入框作为一个<li>标签

注意:你要自己手动编写<table>和<ul>标签。


下面是将上面的ContactForm作为{{ form.as_p }}的渲染出的html:


<p><label for="id_subject">Subject:</label>
<input id="id_subject" type="text" name="subject" maxlength="100" required></p>
<p><label for="id_message">Message:</label>
<textarea name="message" id="id_message" required></textarea></p>
<p><label for="id_sender">Sender:</label>
<input type="email" name="sender" id="id_sender" required></p>
<p><label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself"></p>

注意:Django自动为每个input元素设置了一个id名称,对应label的for参数。


② 手动渲染表单字段

直接{{ form }}虽然好,啥都不用操心,但是往往并不是你想要的,比如你要使用CSS和JS,比如你要引入Bootstarps框架,这些都需要对表单内的input元素进行额外控制,那怎么办呢?手动渲染字段就可以了。


可以通过{{ form.name_of_field }}获取每一个字段,然后分别渲染,如下例所示:


{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="{{ form.message.id_for_label }}">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="{{ form.sender.id_for_label }}">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
{{ form.cc_myself }}
</div>

其中的label标签甚至可以用label_tag()方法来生成,于是可以简写成下面的样子:


<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
</div>
③ 渲染表单错误信息

注意上面的例子中,我们使用{{ form.name_of_field.errors }}模板语法,在表单里处理错误信息。对于每一个表单字段的错误,它其实会实际生成一个无序列表,参考下面的样子:


<ul class="errorlist">
<li>Sender is required.</li>
</ul>

这个列表有个默认的CSS样式类errorlist,如果你想进一步定制这个样式,可以循环错误列表里的内容,然后单独设置样式:


{% if form.subject.errors %}
<ol>
{% for error in form.subject.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}

一切非字段的错误信息,比如表单的错误,隐藏字段的错误都保存在{{ form.non_field_errors }}中,上面的例子,我们把它放在了表单的外围上面,它将被按下面的HTML和CSS格式渲染:


<ul class="errorlist nonfield">
<li>Generic validation error</li>
</ul>
④ 循环表单的字段

如果你的表单字段有相同格式的HTML表现,那么完全可以循环生成,不必要手动的编写每个字段,只需要使用模板语言中的{% for %}循环,减少冗余和重复代码,如下所示:


{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}

下表是{{ field }}中非常有用的属性,这些都是Django内置的模板语言给我们提供的方便:


属性说明{{ field.label }}字段对应的label信息{{ field.label_tag }}自动生成字段的label标签{{ field.id_for_label }}自定义字段标签的id{{ field.value }}当前字段的值,比如一个Email字段的值someone@example.com{{ field.html_name }}指定字段生成的input标签中name属性的值{{ field.help_text }}字段的帮助信息{{ field.errors }}包含错误信息的元素{{ field.is_hidden }}用于判断当前字段是否为隐藏的字段,如果是,返回True{{ field.field }}返回字段的参数列表。例如{{ char_field.field.max_length }}
⑤ 不可见字段

很多时候,我们的表单中会有一些隐藏的不可见的字段,我们需要让它在任何时候都仿佛不存在一般,比如有错误的时候,如果你在页面上显示了不可见字段的错误信息,那么用户会很迷惑,这是哪来的呢?所以,通常我们是不显示不可见字段的错误信息的。


Django提供了两种独立的方法,用于循环那些不可见的和可见的字段,hidden_fields()和visible_fields()。这里,我们可以稍微修改一下前面的例子:


{# 循环那些不可见的字段 #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# 循环可见的字段 #}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
⑥ 重用表单模板

如果你在自己的HTML文件中,多次使用同一种表单模板,那么你完全可以把表单模板存成一个独立的HTML文件,然后在别的HTML文件中通过include模板语法将其包含进来,如下例所示:


# 实际的页面文件中:
{% include "form_snippet.html" %}
-----------------------------------------------------
# 单独的表单模板文件form_snippet.html:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}

如果你的页面同时引用了好几个不同的表单模板,那么为了防止冲突,你可以使用with参数,给每个表单模板取个别名,如下所示:


{% include "form_snippet.html" with form=comment_form %}

在使用的时候就是:


{% for field in comment_form %}
......

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zly717216/article/details/109757181

随机推荐

华为机试题-查找兄弟单词

这篇题解看了牛课网的讨论答案输入描述:先输入字典中单词的个数n,再输入n个单词作为字典单词。再输入一个单词,查找其在字典中兄弟单词的个数m再输入数字k输出描述...

anyanyanyway 阅读(204)

教育智能产品

教育智能产品

​学生了解机器人的发展和应用现状,理解机器人的概念和工作方式,为进一步学习机器人技术的有关知识打下基础。格物斯坦表示:让学生了解机器人各个传感器的功能...

格物斯坦机器人 阅读(802)

@NotNull注解不生效原因

@NotNull注解不生效原因在实体类的属性上加上@NotNull,如下图@DatapublicclassUser(){@NotNullprivateIntegerag...

程序猿—007 阅读(694)

MQTT 协议中文版

MQTT 协议中文版

转mqtt资料  https://www.wenjiangs.com/doc/enzzxdk31...

carl.xu 阅读(334)

中标麒麟操作系统安装

中标麒麟操作系统安装

中标麒麟操作系统安装系统介绍前置软件安装步骤一、新建虚拟机二、选择安装配置三、兼容性选择四、安装客户机操作系统五、选择客户机操作系统六、命名虚拟机七、处理器配置八、虚拟机内存九、选择网络类型十、I/O...

zhf6789 阅读(214)