这个世界像是蒙着一层白雾,看不清这个世界也看不见自己,只是感觉到脚下还踩着坚实的土地,由此证明自己还活着,除了自己一无所有。
使用表单
以前提交表单内容数据都是在HTML中写一个表单,然后发送到后端,后端进行处理。
但是在Django中变得简单明了,首先在应用的目录下新建一个forms.py
# NHDZ/app/forms.py
# coding:utf-8
from django import forms
import datetime
class Login(forms.Form):
username = forms.CharField(label='用户名', widget=forms.TextInput, initial='admin', label_suffix=':x:',required=True)
# 这里设置表单传送过来的数据,并且自动在前端生成表单
# label 表单的前缀显示 '用户名:'
# widget 类型为text
# initial 输入框内的默认值 为 admin
# label_suffix 后缀,默认是 用户名: 现在变成了 用户名:x:
# required 给字段添加必填属性,不能空着。
password = forms.CharField(label='密码', widget=forms.PasswordInput, initial=datetime.date.today(),help_text='在这里输入你的密码')
# initial 默认值 可以动态获取日期
# help_text 帮助文档
然后就能在视图中编写登陆部分的功能
# NHDZ/app/login.py
# coding:utf-8
from .froms import Login
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
# 登陆页面
login_form = Login()
# 实例化表单,然后把表单的内容获取后,渲染到html页面
return render(request, 'login.html', {'login_form': login_form})
def login(request):
# 登陆验证
if request.method == 'POST':
do_login = Login(request.POST)
# 实例化传递过来的数据
if do_login.is_valid():
# 判断数据是否合法
username = do_login.cleaned_data['username']
# 这里的 cleaned_data方法可以清洗数据,然后获取数据
passowrd = do_login.cleaned_data['password']
return HttpResponse(username + '<br>' + passowrd)
然后在templates文件夹新建一个login.html文件,内容如下
<form action="{%url 'login_success'%}" , method='POST'>
{% csrf_token %}
{{login_form}}
<button type="submit">登陆</button>
</form>
最后修改一些路由文件urls.py
# NHDZ/app/urls.py
from django.urls import path
from .views import Index,Add_Images,Add_Texts
from .show import show
from .login import index,login
urlpatterns = [
path('',Index,name='index'),
path('add_texts/',Add_Texts,name='add_texts'),
path('add_images/',Add_Images,name='add_images'),
path('show/<str:user>',show,name='show'),
path('login/',index,name='login'),
path('login_success/',login,name='login_success')
]
这个时候添加功能差不多完成了,访问一下看看是不是生成了表单
点击登陆后,返回结果
自动渲染格式
在演示的login.html中,我只是传入了 就自动生成了表单,但是样式还是非常简陋的,这里使用Django提供自带的样式表渲染就可以变得美美哒
- 将表单渲染成一个表格元素,每个输入框作为一个
标签 - 将表单的每个输入框包裹在一个
标签内 tags
- 将表单渲染成一个列表元素,每个输入框作为一个
- 标签
注意:你要自己手动编写
和
- 标签。
比如我现在把login.html文件修改成这样
<form action="{%url 'login_success'%}" , method='POST'> {% csrf_token %} {{login_form.as_p}} <button type="submit">登陆</button>
现在前端显示的表的样式就变成酱紫
手动渲染格式
在希望引用bootstrap时候,需要手动渲染每个地方的样式表,可以通过如下方式进行获取到表的内容,然后进行渲染
使用直接获取方式
可以使用 表单.属性 的方式获取到表单的内容输入
<form action="{%url 'login_success'%}" , method='POST'> {% csrf_token %} <p>用户id:{{ login_form.username }}</p> # 这里的 login_form.username 就是直接从表单中获取到数据,然后可以自己添加样式 <h2>密码:{{login_form.password}} <button type="submit">登陆</button>
使用迭代表方式获取
传入的数据进行迭代
<form action="{%url 'login_success'%}" , method='POST'> {% csrf_token %} {% for field in login_form %} # 这里对传入的表单迭代
{{ field.label_tag }}:{{ field }} # field 是表单输入的内容,field.label_tag 是表单的样式表 # 然后使用 p 标签进行渲染,当然可以把p标签替换css样式
{{ field.errors }} # 如果表单错误,提示错误内容 {% endfor %} <button type="submit">登陆</button>渲染表单错误信息
在表单里处理错误信息。对于每一个表单字段的错误,它其实会实际生成一个无序列表,参考下面的样子:
<ul class="errorlist"> <li>Sender is required.</li> </ul>
这个列表有个默认的CSS样式类errorlist,如果你想进一步定制这个样式,可以循环错误列表里的内容,然后单独设置样式:
{% if login_form.errors %}
-
{% for error in form.username.errors %}
- {{ error|escape }} {% endfor %}
一切非字段的错误信息,比如表单的错误,隐藏字段的错误都保存在中,上面的例子,我们把它放在了表单的外围上面,它将被按下面的HTML和CSS格式渲染:
<ul class="errorlist nonfield"> <li>Generic validation error</li> </ul>
使用 CSS 样式表
总结了一下,可以通过三种(说到底就是两种)方式设置层叠样式表
后端处理
在Django编写forms.py表单模型的时候,能够通过设置Field类的属性设置样式,比如
class Login(forms.Form): username = forms.CharField(label='用户名', widget=forms.TextInput(attrs={'size': '20'})) # 代表大小为20px
然后 在templates的login.html修改成
<form action="{%url 'login_success'%}" , method='POST'> {% csrf_token %} {{login_form}} <button type="submit">登陆</button>
结果如下
使用前端处理
如上文的手动渲染格式一样,使用field.xxx获取表单的属性,然后自己在前端html编写css
需要注意的是,如果你在前端手动获取了表单的内容数据后然后自己写css渲染后,后端代码中设置的样式不起作用
半自动处理
前端框架习惯bootstrap,实践后发现能通过前后端设置bootstrap的属性,我为了省事儿没有在static文件夹保存bootstrap的文件,直接引用了
后端代码如下:
class Login(forms.Form): username = forms.CharField(label='用户名', widget=forms.TextInput(attrs={'class': 'form-control'})) # class:form-control 是bootstrap的输入框的一个样式
前端代码如下:
<head> <meta charset="UTF-8"> <title>登陆</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> # 通过这直接远程引用了bootstrap </head> <body> <form action="{%url 'login_success'%}" , method='POST'> {% csrf_token %} <div class="col-md-3"> # 这里是属于bootartap的一个栅栏样式 {{login_form}} <button type="submit">登陆</button> </form> </div>
返回的结果:
熟悉的界面~
上传文件
走FORMS
首先,写一个form模型,它必须包含一个FileField:
# forms.py from django import forms class UploadFileForm(forms.Form): title = forms.CharField(max_length=50) file = forms.FileField()
处理这个表单的视图将在request.FILES中收到文件数据,可以用request.FILES[‘file’]来获取上传文件的具体数据,其中的键值‘file’是根据file = forms.FileField()的变量名来的。
注意:request.FILES只有在请求方法为POST,并且提交请求的
下面是一个接收上传文件的视图范例:
# views.py from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import UploadFileForm # 另外写一个处理上传过来的文件的方法,并在这里导入 from somewhere import handle_uploaded_file def upload_file(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) # 注意获取数据的方式 if form.is_valid(): handle_uploaded_file(request.FILES['file']) return HttpResponseRedirect('/success/url/') else: form = UploadFileForm() return render(request, 'upload.html', {'form': form})
请注意,必须将request.FILES传递到form的构造函数中。
form = UploadFileForm(request.POST, request.FILES)
下面是一个处理上传文件的方法的参考例子:
def handle_uploaded_file(f): with open('some/file/name.txt', 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk)
遍历UploadedFile.chunks(),而不是直接使用read()方法,能确保大文件不会占用系统过多的内存。
走MODELS
如果是通过模型层的model来指定上传文件的保存方式的话,使用ModelForm更方便。 调用form.save()的时候,文件对象会保存在相应的FileField的upload_to参数指定的地方。
from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import ModelFormWithFileField def upload_file(request): if request.method == 'POST': form = ModelFormWithFileField(request.POST, request.FILES) if form.is_valid(): # 这么做就可以了,文件会被保存到Model中upload_to参数指定的位置 form.save() return HttpResponseRedirect('/success/url/') else: form = ModelFormWithFileField() return render(request, 'upload.html', {'form': form})
如果手动构造一个对象,还可以简单地把文件对象直接从request.FILES赋值给模型:
from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import UploadFileForm from .models import ModelWithFileField def upload_file(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): instance = ModelWithFileField(file_field=request.FILES['file']) instance.save() return HttpResponseRedirect('/success/url/') else: form = UploadFileForm() return render(request, 'upload.html', {'form': form})
前端表单常用属性
属性 说明 {{ login_form.label }} 字段对应的label信息 {{ login_form.label_tag }} 自动生成字段的label标签,注意与{{ login_form.label }}的区别。 {{ login_form.id_for_label }} 自定义字段标签的id {{ login_form.value }} 当前字段的值,比如一个Email字段的值someone@example.com {{ login_form.html_name }} 指定字段生成的input标签中name属性的值 {{ login_form.help_text }} 字段的帮助信息 {{ login_form.errors }} 包含错误信息的元素 {{ login_form.is_hidden }} 用于判断当前字段是否为隐藏的字段,如果是,返回True {{ login_form.field }} 返回字段的参数列表。例如{{ char_field.field.max_length }}
表单内置的Field类
对于每个字段类,介绍其默认的widget,当输入为空时返回的值,以及采取何种验证方式。‘规范化为’表示转换为PYthon的何种对象。可用的错误信息键,表示该字段可自定义错误信息的类型(字典的键)。
1. BooleanField
默认的Widget:CheckboxInput 空值:False 规范化为:Python的True或者False 可用的错误信息键:required
##2. CharField
默认的Widget:TextInput 空值:与empty_value给出的任何值。 规范化为:一个Unicode 对象。 验证max_length或min_length,如果设置了这两个参数。 否则,所有的输入都是合法的。 可用的错误信息键:min_length, max_length, required 有四个可选参数: max_length,min_length:设置字符串的最大和最小长度。 strip:如果True(默认),去除输入的前导和尾随空格。 empty_value:用来表示“空”的值。 默认为空字符串。
##3. ChoiceField
默认的Widget:Select
空值:’’(一个空字符串)
规范化为:一个Unicode 对象。
验证给定的值是否在选项列表中。
可用的错误信息键:required, invalid_choice
参数choices:用来作为该字段选项的一个二元组组成的可迭代对象(例如,列表或元组)或者一个可调用对象。格式与用于和ORM模型字段的choices参数相同。##4. TypedChoiceField
像ChoiceField一样,只是还有两个额外的参数:coerce和empty_value。默认的Widget:Select 空值:empty_value参数设置的值。 规范化为:coerce参数类型的值。 验证给定的值在选项列表中存在并且可以被强制转换。 可用的错误信息的键:required, invalid_choice
##5. DateField
默认的Widget:DateInput
空值:None
规范化为:datetime.date对象。
验证给出的值是一个datetime.date、datetime.datetime 或指定日期格式的字符串。
错误信息的键:required, invalid
接收一个可选的参数:input_formats。一个格式的列表,用于转换字符串为datetime.date对象。如果没有提供input_formats,默认的输入格式为: ['%Y-%m-%d', # '2006-10-25' '%m/%d/%Y', # '10/25/2006' '%m/%d/%y'] # '10/25/06' 另外,如果你在设置中指定USE_L10N=False,以下的格式也将包含在默认的输入格式中: ['%b %d %Y', # 'Oct 25 2006' '%b %d, %Y', # 'Oct 25, 2006' '%d %b %Y', # '25 Oct 2006' '%d %b, %Y', # '25 Oct, 2006' '%B %d %Y', # 'October 25 2006' '%B %d, %Y', # 'October 25, 2006' '%d %B %Y', # '25 October 2006' '%d %B, %Y'] # '25 October, 2006'
##6. DateTimeField
默认的Widget:DateTimeInput
空值:None
规范化为:Python的datetime.datetime对象。
验证给出的值是一个datetime.datetime、datetime.date或指定日期格式的字符串。
错误信息的键:required, invalid
接收一个可选的参数:input_formats如果没有提供input_formats,默认的输入格式为: ['%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' '%Y-%m-%d %H:%M', # '2006-10-25 14:30' '%Y-%m-%d', # '2006-10-25' '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' '%m/%d/%Y %H:%M', # '10/25/2006 14:30' '%m/%d/%Y', # '10/25/2006' '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' '%m/%d/%y %H:%M', # '10/25/06 14:30' '%m/%d/%y'] # '10/25/06'
7. DecimalField
默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。 空值:None 规范化为:Python decimal对象。 验证给定的值为一个十进制数。 忽略前导和尾随的空白。 错误信息的键:max_whole_digits, max_digits, max_decimal_places,max_value, invalid, required,min_value 接收四个可选的参数: max_value,min_value:允许的值的范围,需要赋值decimal.Decimal对象,不能直接给个整数类型。 max_digits:值允许的最大位数(小数点之前和之后的数字总共的位数,前导的零将被删除)。 decimal_places:允许的最大小数位。
##8. DurationField
默认的Widget:TextInput
空值:None
规范化为:Python timedelta。
验证给出的值是一个字符串,而且可以转换为timedelta对象。
错误信息的键:required, invalid.
9. EmailField
默认的Widget:EmailInput
空值:’’(一个空字符串)
规范化为:Unicode 对象。
使用正则表达式验证给出的值是一个合法的邮件地址。
错误信息的键:required, invalid
两个可选的参数用于验证,max_length 和min_length。##10. FileField
默认的Widget:ClearableFileInput
空值:None
规范化为:一个UploadedFile对象,它封装文件内容和文件名到一个对象内。
验证非空的文件数据已经绑定到表单。
错误信息的键:missing, invalid, required, empty, max_length
具有两个可选的参数用于验证:max_length 和 allow_empty_file。##11. FilePathField
默认的Widget:Select
空值:None
规范化为:Unicode 对象。
验证选择的选项在选项列表中存在。
错误信息的键:required, invalid_choice
这个字段允许从一个特定的目录选择文件。 它有五个额外的参数,其中的path是必须的:path:要列出的目录的绝对路径。 这个目录必须存在。 recursive:如果为False(默认值),只用直接位于path下的文件或目录作为选项。如果为True,将递归访问这个目录,其内所有的子目录和文件都将作为选项。 match:正则表达模式;只有具有与此表达式匹配的文件名称才被允许作为选项。 allow_files:可选。默认为True。表示是否应该包含指定位置的文件。它和allow_folders必须有一个为True。 allow_folders可选。默认为False。表示是否应该包含指定位置的目录。
##12. FloatField
默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。
空值:None
规范化为:Float 对象。
验证给定的值是一个浮点数。
错误信息的键:max_value, invalid, required, min_value
接收两个可选的参数用于验证,max_value和min_value,控制允许的值的范围。##13. ImageField
默认的Widget:ClearableFileInput
空值:None
规范化为:一个UploadedFile 象,它封装文件内容和文件名为一个单独的对象。
验证文件数据已绑定到表单,并且该文件是Pillow可以解析的图像格式。
错误信息的键:missing, invalid, required, empty, invalid_image
使用ImageField需要安装Pillow(pip install pillow)。如果在上传图片时遇到图像损坏错误,通常意味着使用了Pillow不支持的格式。##14. IntegerField
默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。
空值:None
规范化为:Python 整数或长整数。
验证给定值是一个整数。 允许前导和尾随空格,类似Python的int()函数。
错误信息的键:max_value, invalid, required, min_value
两个可选参数:max_value和min_value,控制允许的值的范围。##15. GenericIPAddressField
包含IPv4或IPv6地址的字段。默认的Widget:TextInput 空值:''(一个空字符串) 规范化为:一个Unicode对象。 验证给定值是有效的IP地址。 错误信息的键:required, invalid 有两个可选参数:protocol和unpack_ipv4
##16. MultipleChoiceField
默认的Widget:SelectMultiple
空值:[](一个空列表)
规范化为:一个Unicode 对象列表。
验证给定值列表中的每个值都存在于选择列表中。
错误信息的键:invalid_list, invalid_choice, required
##17. TypedMultipleChoiceField
类似MultipleChoiceField,除了需要两个额外的参数,coerce和empty_value。默认的Widget:SelectMultiple 空值:empty_value 规范化为:coerce参数提供的类型值列表。 验证给定值存在于选项列表中并且可以强制。 错误信息的键:required, invalid_choice
##18. NullBooleanField
默认的Widget:NullBooleanSelect
空值:None
规范化为:Python None, False 或True 值。
不验证任何内容(即,它从不引发ValidationError)。
##19.RegexField
默认的Widget:TextInput
空值:’’(一个空字符串)
规范化为:一个Unicode 对象。
验证给定值与某个正则表达式匹配。
错误信息的键:required, invalid
需要一个必需的参数:regex,需要匹配的正则表达式。还可以接收max_length,min_length和strip参数,类似CharField。
##20. SlugField
默认的Widget:TextInput
空值:’’(一个空字符串)
规范化为:一个Unicode 对象。
验证给定的字符串只包括字母、数字、下划线及连字符。
错误信息的键:required, invalid
此字段用于在表单中表示模型的SlugField。##21. TimeField
默认的Widget:TextInput
空值:None
规范化为:一个Python 的datetime.time 对象。
验证给定值是datetime.time或以特定时间格式格式化的字符串。
错误信息的键:required, invalid
接收一个可选的参数:input_formats,用于尝试将字符串转换为有效的datetime.time对象的格式列表。如果没有提供input_formats,默认的输入格式为: '%H:%M:%S', # '14:30:59' '%H:%M', # '14:30'
##22. URLField
默认的Widget:URLInput
空值:’’(一个空字符串)
规范化为:一个Unicode 对象。
验证给定值是个有效的URL。
错误信息的键:required, invalid
可选参数:max_length和min_length##23. UUIDField
默认的Widget:TextInput
空值:’’(一个空字符串)
规范化为:UUID对象。
错误信息的键:required, invalid
##24. ComboField
默认的Widget:TextInput
空值:’’(一个空字符串)
规范化为:Unicode 对象。
根据指定为ComboField的参数的每个字段验证给定值。
错误信息的键:required, invalid
接收一个额外的必选参数:fields,用于验证字段值的字段列表(按提供它们的顺序)。>>> from django.forms import ComboField >>> f = ComboField(fields=[CharField(max_length=20), EmailField()]) >>> f.clean('test@example.com') 'test@example.com' >>> f.clean('longemailaddress@example.com') Traceback (most recent call last): ... ValidationError: ['Ensure this value has at most 20 characters (it has 28).']
##25. MultiValueField
默认的Widget:TextInput
空值:’’(一个空字符串)
规范化为:子类的compress方法返回的类型。
根据指定为MultiValueField的参数的每个字段验证给定值。
错误信息的键:incomplete, invalid, required
##26. SplitDateTimeField
默认的Widget:SplitDateTimeWidget
空值:None
规范化为:Python datetime.datetime 对象。
验证给定的值是datetime.datetime或以特定日期时间格式格式化的字符串。
错误信息的键:invalid_date, invalid, required, invalid_time本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Sxadmin blog! - 将表单的每个输入框包裹在一个