Django-表单处理

这个世界像是蒙着一层白雾,看不清这个世界也看不见自己,只是感觉到脚下还踩着坚实的土地,由此证明自己还活着,除了自己一无所有。

使用表单

以前提交表单内容数据都是在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提供自带的样式表渲染就可以变得美美哒

  1. 将表单渲染成一个表格元素,每个输入框作为一个标签
  2. 将表单的每个输入框包裹在一个

    标签内 tags

  3. 将表单渲染成一个列表元素,每个输入框作为一个
  4. 标签

注意:你要自己手动编写

    标签。

比如我现在把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 %}
  1. {{ error|escape }}
  2. {% endfor %}
{% endif %}

一切非字段的错误信息,比如表单的错误,隐藏字段的错误都保存在中,上面的例子,我们把它放在了表单的外围上面,它将被按下面的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,并且提交请求的

具有enctype=”multipart/form-data”属性时才有效。 否则,request.FILES将为空。

下面是一个接收上传文件的视图范例:

# 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类

转载地址,侵删URL

对于每个字段类,介绍其默认的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

坚持原创技术分享,您的支持将鼓励我继续创作!
------ 本文结束 ------

版权声明

LangZi_Blog's by Jy Xie is licensed under a Creative Commons BY-NC-ND 4.0 International License
由浪子LangZi创作并维护的Langzi_Blog's博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Langzi_Blog's 博客( http://langzi.fun ),版权所有,侵权必究。

0%