Django第3章: Form表单

1. 常规表单
2. django中的form表单

form表单使用介绍

  1. 页面与web服务器交互数据最重要的方式;
  2. input标签类型: text, password, file;
  3. 默认方式method=get,所有信息都会在url后面显示,表单提交指定为method=post;
  4. 注意,若需要将数据发送到后端,input标签必须指定name属性,否则不会发送;
  5. 传输的数据以键值对形式保存在request.POST中, 键的值即为name属性值;
  6. 文件上传: 由于上传文件时在客户端与服务端传输的是二进制数据,与字符串数据不一样。传输二进制数据,不管是在form表单,还是在Ajax中,都有自己的传输方式。
    在form表单中,上传文件时要使用分片传输的方式enctype="multipart/form-data"

    • 若没有指定form的传输方式: file数据保存在request.POST中, 一般是文件名的str形式;
    • 若指定了文件传输类型: enctype="multipart/form-data",表单提交后文件以InMemoryUploadedFile的类对象单独保存在request.FILES中,
  7. 保存文件: 后台接收的文件对象无法直接通过open方法读取, 直接遍历文件对象即可;
    // 接受文件对象并保存至服务器
    file_obj = request.FILES.get('upload_file')
    f1 = open(file_obj.name, "wb")
    # 方法1
    for i in file_obj:
        f1.write(i)
    # 方法2
    for i in file_obj.chunks():
        f1.write(i)


Django的form表单介绍

form表单的升级版, 可以给表单元素扩展许多功能:

  1. 在模板生成html的input标签;
  2. 验证用户数据并显示错误信息;
  3. 保留上次提交数据;
  4. 初始化页面显示内容;

form字段及参数

required=True,               是否允许为空
widget=None,                 HTML插件
disabled=False,              是否可以编辑
initial=None,                初始值
label=None,                  用于生成Label标签或显示内容
help_text='',                帮助信息(在标签旁边显示)
error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}, 此处和model字段定义错误信息类似, 也有max_length, min_length等错误信息code

show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
validators=[],               自定义验证规则
localize=False,              是否支持本地化
label_suffix=None            Label内容后缀

CharField
    max_length=None,             最大长度
    min_length=None,             最小长度
    strip=True                   是否移除用户输入空白

IntegerField
    max_value=None,              最大值
    min_value=None,              最小值

FloatField
    ...

DecimalField
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             总长度
    decimal_places=None,         小数位长度

RegexField
    regex,                      自定制正则表达式
    max_length=None,            最大长度
    min_length=None,            最小长度
    error_message=None,         忽略错误信息,错误信息使用   error_messages={'invalid': '...'}

EmailField
    ...

# 重要
FileField
    allow_empty_file=False     是否允许空文件

ImageField
    需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        1. form表单中 enctype="multipart/form-data"
        2. view函数中 obj = MyForm(request.POST, request.FILES)

URLField
    ...

BooleanField
    ...

ChoiceField
    choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,默认select插件
    label=None,                Label内容
    initial=None,              初始值
    help_text='',              帮助提示

FilePathField       文件选项,目录下文件显示在页面中
    path,                      文件夹路径
    match=None,                正则匹配
    recursive=False,           递归下面的文件夹
    allow_files=True,          允许文件
    allow_folders=False,       允许文件夹
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''

常用控件

// radio单选按钮,值为字符串==========================
gender = forms.ChoiceField(
    choices=((1, '男性'),(2, '女性'), (3, '中性'), ), initial=1,
    widget=widgets.RadioSelect
)

gender = forms.CharField(
    initial=1, widget=widgets.RadioSelect(choices=((1, '男性'),(2, '女性'), (3, '中性'), ))
)

// 单select,值为字符串========================================
user = fields.CharField(
     initial=2,
     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
)

user = fields.ChoiceField(
     choices=((1, '上海'), (2, '北京'),),
     initial=2,
     widget=widgets.Select
)

// 多选select,值为列表==========================================
user = fields.MultipleChoiceField(
     choices=((1,'上海'),(2,'北京'),),
     initial=[1,],
     widget=widgets.SelectMultiple
)

// 单checkbox
gender = forms.ChoiceField(initial=[2, ],choices=((1, '上海'), (2, '北京'),), widget=widgets.CheckboxInput)

// 多选checkbox,值为列表
user = fields.MultipleChoiceField(
     initial=[2, ],
     choices=((1, '上海'), (2, '北京'),),
     widget=widgets.CheckboxSelectMultiple
)
关于使用select等控件时的取值问题
  1. 先将内容以元祖嵌套格式取出, Obj.objects.all().values_list(‘id‘, ‘name‘);
  2. 作为参数传入;
class UserForm(forms.Form):
    choices = City.objects.all().values_list('id', 'name')
    hometown = forms.ChoiceField(initial=2, widget=widgets.Select(choices=choices))

Django的form使用步骤

  1. 创建后台表单验证类,继承form.Form;

    from django import forms
    from django.forms import widgets
    
    class UserForm(forms.Form):
        username = forms.CharField(min_length=2, max_length=12, label='用户名', error_messages={'required': '用户名不能为空', 'min_length': '必须大于2位'}, widget=widgets.TextInput(attrs={"placeholder": "用户名", "class": "form-control s", 'label':'username', }))
    # 可以在后端定制input样式,直接给即将生成的input标签增加属性
        password = forms.CharField(label='密码',min_length=4,widget=widgets.PasswordInput(attrs={"placeholder": "密码","class": "form-control"}))
    
        email = forms.EmailField(label='邮箱', widget=widgets.PasswordInput(attrs={"placeholder": "密码","class": "form-control"}))
    
        gender = forms.ChoiceField(choices=((1, 'male'),(2, 'female')), initial=1, widget=widgets.RadioSelect)
    
        hometown = forms.CharField(
            initial=2,
            widget=widgets.Select(choices=((1, '武汉'), (2, '广州'),))
    )
    
  2. 页面根据类的对象自动创建html标签, 注意, 在form标签中加上novalidate可以关闭浏览器的自动验证功能, 方便前期调试;
    <link rel="stylesheet" href="{% static 'css/bootstrap.css' %}">
    
    <div class="container form">
    <div class="row">
         <div class="col-md-8">
            <form action="" method="post" enctype="multipart/form-data" novalidate>
                <div class="form-group">
                    <p>username:{{ form.username }}<span>{{ error_msg.username.0 }}</span></p>
                </div>
                <div class="form-group">
                    <p>password:{{ form.password }}<span>{{ error_msg.password.0 }}</span></p>
                </div>
                <div class="form-group">
                    <p>email:{{ form.email }}<span>{{ error_msg.email.0 }}</span></p>
                </div>
                <div class="form-group">
                    <p>gender:{{ form.gender }}<span>{{ error_msg.gender.0 }}</span></p>
                </div>
                <div class="form-group">
                    <p>hometown:{{ form.hometown }}<span>{{ error_msg.gender.0 }}</span></p>
                </div>
                <div class="form-group"><input type="submit"></div>
                {% csrf_token %}
            </form>
         </div>
    
        </div>
    
    </div>
    
  3. 视图函数接收表单数据, 判断并返回信息
    def register(request):
    error_msg = ''
    if request.method == 'GET':
        # 1. 实例化空form对象, 并传到模板,生成空的input标签
        my_form = UserForm()
        return render(request, 'register.html', {"form": my_form, 'error_msg': error_msg})
    
    if request.method == "POST":
        # 1. 创建form对象,随后利用前端form提交的信息对齐进行填充
        form_post = UserForm(request.POST)
    
        # 2. 检查提交的表单语法是否正确
        if form_post.is_valid():
            print(form_post.clean())
            # 默认检测所有的输入框不能为空
            # 特有的取值方法:通过cleaned_data属性取到所有的输入值
            username = form_post.cleaned_data.get('username', '')
            password = form_post.cleaned_data.get('password', '')
            email = form_post.cleaned_data.get('email', '')
    
        else:
            # 检查错误信息
            # 可以用ie浏览器检测,chrome和火狐都会默认在前端显示错误,不会提交
            error_msg = form_post.errors
            print(error_msg)  # <class 'django.forms.utils.ErrorDict'>
            return HttpResponse('信息有误')

内置错误信息提示

在前面三个步骤的基础上, 对于错误在页面的提示作以下说明,见代码;
注意:

# 简单的错误信息定制,
error_messages={
    'required': '用户名不能为空', 'min_length': '必须大于*位',
    'invalid' : '****', 'max_length': '不能超过*位',...
},

# is.valid()没通过的分支
error_msg = form_post.errors
print(error_msg)  # <class 'django.forms.utils.ErrorDict'>
return render(request, 'register.html', {
    "error_msg": error_msg,
    'form': form_post,
})

# html页面
<span class="errors">{{ error_msg.username.0 }}</span>
# 有对应的字段错误,就取值并显示

自定制错误信息(重点)

正则匹配的自定义验证
  1. 存在多条验证时, 以列表或者元祖形式导入实例化的RegexValidator对象, django会按照顺序逐个验证,直到抛出错误信息;
  2. 传入两个参数: 匹配的正则表达式错误信息;
  3. 原理是若输入与正则不匹配,则抛出ValidationError(错误信息)
from django.form import Form
from django.core.validators import RegexValidator

class UserForm(Form):
    username = forms.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
        widget=widgets.TextInput(attrs={'class': 'form-control'}))
自定义验证函数
from django.core.exceptions import ValidationError
import re

def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')

class UserForm(forms.Form):
    username = forms.CharField(validators=[mobile_validate, ], widget=widgets.TextInput(attrs={'class': 'form-control'}),)
重载内置的clean_field方法
  1. 在form字段中定义的验证完成后,会执行clean_field()方法;
  2. 此时通过cleaned_data取出要进一步判断的值;
  3. 自定义验证函数必须有返回值, 即合格的值, 不合格直接抛出自定义的错误信息即可;
from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError

class UserForm(Form):
    username = forms.CharField(widget=widgets.TextInput(attrs={'class': 'form-control'}),)

    def clean_username(self):
        value = self.cleaned_data['username']
        if value == 'alex':
            raise ValidationError('用户名已存在')
        return value
全局自定制验证clean方法
  1. 实现前提条件: 因为clean(self)是在clean_field(self)之后运行的;
  2. 若验证没用过, 自定制的错误信息会存储在django.forms.utils.ErrorDict中, __all__:[‘错误信息‘, ];
  3. 在前端不能直接通过errors_dict.key.0取出,需要自定义过滤器,取出__all__的值;
# 例如:验证用户名和邮箱是否一致

// 后台自定制多字段验证方法==============
def clean(self):
    if self.cleaned_data.get('username') != self.cleaned_data.get('email'):
        raise ValidationError('用户名和邮箱不一致')
    else:
        return self.cleaned_data

// 自定义过滤器==========================
from django import template
register = template.Library()

@register.filter
def get_error(error_dict):
    return error_dict.get('__all__')

// 前端取值=============================
 <div id="error_msg">
     {% if error_msg %}
        {{ error_msg|get_error }}
     {% endif %}
 </div>

原文地址:https://www.cnblogs.com/fqh202/p/8719798.html

时间: 2024-08-29 11:55:31

Django第3章: Form表单的相关文章

Django学习系列之Form表单和ajax

ajax 通过ajax发送一条数据 定义urls.py from django.conf.urls import url from django.contrib import admin from cmdb import views urlpatterns = [ url(r'^ajax_demo/', views.ajax_demo), ] 定义views.py from django.shortcuts import render from django.shortcuts import H

django forms自带form表单

from django import forms from app_name import models class class_name(forms.ModelForm) class Meta: model = models.Book //默认是所有的都匹配 fields = ('name','pub_date') //提供要匹配的字段 widget = { 'name':forms.TextInput(attrs = {'class':'form-control'}) 前端样式 }

django,form表单,数据库增删改查

Django 02 复习:  Django下载:   在命令行输入:    pip3 install django==1.11.11    在这里不要用最新的3.7,推荐使用3.6/3.5/3.4    判断下载成功:     django-admin    创建django项目:     django-admin startproject 项目名     会创建跟项目同名的文件夹     settings.py 暴露给用户可配置的配置文件     urls.py     路由与视图函数对应文件

django之form表单验证

django中的Form一般有两种功能: 输入html 验证用户输入 #!/usr/bin/env python # -*- coding:utf-8 -*- import re from django import forms from django.core.exceptions import ValidationError def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]

Django--分页器(paginator)、Django的用户认证、Django的FORM表单

分页器(paginator) >>> from django.core.paginator import Paginator >>> objects = ['john', 'paul', 'george', 'ringo'] >>> p = Paginator(objects, 2) >>> p.count #数据总数 4 >>> p.num_pages #总页数 2 >>> type(p.page

Django Form表单

Django  Form 表单 在实际的生产环境中比如登录和验证的时候,我们一般都使用Jquery+ajax来判断用户的输入是否为空,假如JS被禁用的话,咱们这个认证屏障是不是就消失了呢?(虽然一般不会禁用掉但是还是存在风险) 所以我们一般做两种认证一种是前端做一遍认证,在后端做一遍认证. 首先咱们看一下下面的案例: from django.shortcuts import render # Create your views here. def user_list(request): host

Python自动化运维系列之Django Form表单验证

Form表单验证 Django核心功能组件之一,虽然也可以在前端使用JS对表单验证, 但是Django中已经为我们准备好的Form功能还算是很强大的,有时候比较适合运维,为我们简化了很多前端开发工作. Django最主要的几个功能有4个     ·  生成HTML标签     ·  验证数据(表单错误信息提示)     ·  HTML 表单保留上次提交数据     ·  初始化页面表单内容 Django的Form内容还是挺多的,我们可以从一个简单的登陆验证例子来看看Form的基本功能使用 1)新

Django基础之Form表单验证

Form表单验证 1.创建Form类(本质就是正则表达式的集合) from django.forms import Form from django.forms import fields from django.forms import widgets from Mybbs.models import * import re class UserForm(Form): username = fields.CharField( required=True, error_messages={'re

Django Form 表单(上)

我们已经知道了在Django里面如何从前端向后台发送数据的基本操作.( http://beanxyz.blog.51cto.com/5570417/1944978 )在之前的例子里面,我们的HTML模板里面的form表单都是手动创建的,对于提交的数据类型格式也需要自己写正则表达式进行确认.(例如AJAX的例子http://beanxyz.blog.51cto.com/5570417/1951021  ) 如果表单很多的话,手动处理这些东西会很费时间.Django提供了一个form的功能,可以根据