【Django】Form组件

目录

  • Form组件介绍
  • 常用字段与插件
    • Form组件中所有内置字段
    • 从数据库中获取数据
  • 校验示例
    • 检验手机号是否合法

      • 方式一(基本操作)
      • 方式二(自定义验证规则)
      • 方式三(利用钩子)
    • 验证密码一致性
  • 钩子
    • 局部钩子
    • 全局钩子
  • 进阶
    • 批量添加样式
    • ModelForm
  • Form套Form

@

***

Form组件介绍

在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来。

与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度和格式等正不正确。如果用户输入的内容有错误就需要在页面上相应的位置显示对应的错误信息。

Django form组件就实现了上面的功能。

先总结一下,form组件的主要功能如下:

  1. 生成页面可用的HTML标签
  2. 对用户提交的数据进行校验
  3. 保留上传输入的内容

    ***

    一个简单的注册示例

    form文件:

from django import forms

# 按照Django form组件的要求自己写一个类
# 且必须继承forms.Form
class RegForm(forms.Form):
    user = forms.CharField(label="名称")
    pwd = forms.CharField(label="密码", min_length=6)

视图文件:

from django.shortcuts import render, HttpResponse
from blog01 import forms  # 导入上面的form文件

def register(request):
    form_obj = forms.RegForm()
    if request.method == ‘POST‘:
        form_obj = forms.RegForm(request.POST)
        if form_obj.is_valid():
            # 只有执行了is_valid之后,才可执行cleaned_data,否则会报错
            # cleaned_data的数据是经过校验的
            print(form_obj.cleaned_data)
            return HttpResponse("注册成功!")
    return render(request, ‘register.html‘, {‘form‘: form_obj})

HTML文件:

<body>
{# novalidate:阻止验证(form组件会自动验证)#}
<form action="" method="post" novalidate>
{% csrf_token %}
    {# {{ form.as_p }}  以p标签的形式自动生成 #}
    {# 下面为简单的自定义形式 #}
    <p>
        {{ form.user.label }}
        {{ form.user }}
        {# 错误提示信息 #}
        {# {{ form.errors }}  生成form表单的所有错误信息(全局错误信息)#}
        {# <span style="color: red">{{ form.user.errors }}</span>  指定字段的所有错误信息 #}
        <span style="color: red">{{ form.user.errors.0 }}</span> {# 指定字段的所有错误信息的第一个 #}
    </p>
    <p>
        {{ form.pwd.label }}
        {{ form.pwd }}
        <span style="color: red">{{ form.pwd.errors.0 }}</span>
    </p>
    <button>注册</button>
</form>
</body>


常用字段与插件

from django import forms

class RegForm(forms.Form):
    user = forms.CharField(
        label="名称",  # 用于生成label标签或显示内容
        # required=False,  # 为False时,允许为空
        min_length=2,  # 最小长度
        max_length=6,  # 最大长度
        initial=‘zyk01‘,  # 初始值
        error_messages={
            ‘required‘: "用户名不能为空",
            ‘invalid‘: "用户名格式错误",
            ‘min_length‘: "用户名最短2位",
        }  # 自定义错误提示
    )

    pwd = forms.CharField(
        label="密码",
        min_length=6,
        error_messages={
            ‘required‘: "密码不能为空",
            ‘invalid‘: "密码格式错误",
            ‘min_length‘: "密码最短6位",
        },
        widget=forms.widgets.PasswordInput(),  # 指定input的type类型为password
    )

    # ===================================================
    #
    # ===================================================

    """checkbox标签(单选)"""
    keep = forms.fields.ChoiceField(
        label="记住密码",
        initial=‘checked‘,  # 默认选中
        widget=forms.widgets.CheckboxInput(),
    )

    """checkbox标签(多选)"""
    hobby01 = forms.fields.MultipleChoiceField(
        label="爱好01",
        choices=((1, "篮球"), (2, "足球"), (3, "乒乓球"),),
        initial=[1, 2],  # 默认选中1, 2
        widget=forms.widgets.CheckboxSelectMultiple(),
    )

    """radioSelect(等价于<input type="radio">)"""
    gender = forms.fields.ChoiceField(
        label="性别",
        choices=((1, "男"), (2, "女"), (3, "阴阳人"),),
        initial=1,  # 默认选中1
        widget=forms.widgets.RadioSelect(),
    )

    """Select标签"""
    hobby02 = forms.fields.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好02",
        initial=3,  # # 默认选中3
        # widget=forms.widgets.Select(),  # 实现单选Select
        widget=forms.widgets.SelectMultiple(),  # 实现多选Select
    )

Form组件中所有内置字段

Field
    required=True,               是否允许为空
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    help_text=‘‘,                帮助信息(在标签旁边显示)
    error_messages=None,         错误信息 {‘required‘: ‘不能为空‘, ‘invalid‘: ‘格式错误‘}
    validators=[],               自定义验证规则
    localize=False,              是否支持本地化
    disabled=False,              是否可以编辑
    label_suffix=None            Label内容后缀

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

IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值

FloatField(IntegerField)
    ...

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

BaseTemporalField(Field)
    input_formats=None          时间格式化   

DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12

DurationField(Field)            时间间隔:%d %H:%M:%S.%f
    ...

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

EmailField(CharField)
    ...

FileField(Field)
    allow_empty_file=False     是否允许空文件

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

URLField(Field)
    ...

BooleanField(Field)
    ...

NullBooleanField(BooleanField)
    ...

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

ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查询数据库中的数据
    empty_label="---------",   # 默认空显示内容
    to_field_name=None,        # HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选

ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField

TypedChoiceField(ChoiceField)
    coerce = lambda val: val   对选中的值进行一次转换
    empty_value= ‘‘            空值的默认值

MultipleChoiceField(ChoiceField)
    ...

TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   对选中的每一个值进行一次转换
    empty_value= ‘‘            空值的默认值

ComboField(Field)
    fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])

MultiValueField(Field)
    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用

SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:[‘%Y--%m--%d‘, ‘%m%d/%Y‘, ‘%m/%d/%y‘]
    input_time_formats=None    格式列表:[‘%H:%M:%S‘, ‘%H:%M:%S.%f‘, ‘%H:%M‘]

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

GenericIPAddressField
    protocol=‘both‘,           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用

SlugField(CharField)           数字,字母,下划线,减号(连字符)
    ...

UUIDField(CharField)           uuid类型

从数据库中获取数据

在使用选择标签时,需要注意choices的选项可以从数据库中获取,但由于是静态字段,==获取的值无法实施更新==,所以需要自定义构造方法从而达到此目的.

from django import forms
from blog01 import models

class RegForm(forms.Form):
    hobby03 = forms.fields.ChoiceField(
        label="爱好03",
        # choices=models.Hobby.objects.values_list(‘id‘, ‘name‘),
        widget=forms.widgets.CheckboxSelectMultiple(),
    )

    def __init__(self, *args, **kwargs):
        super(RegForm, self).__init__(*args, **kwargs)
        # self.fields[‘hobby03‘].choices = ((1, ‘Python‘), (2, ‘Django‘),)
        self.fields[‘hobby03‘].choices =  models.Hobby.objects.values_list(‘id‘,‘name‘)


校验示例


检验手机号是否合法

视图文件:

from django.shortcuts import render, HttpResponse
from blog01 import forms  # 导入form文件

def register(request):
    form_obj = forms.RegForm()
    if request.method == ‘POST‘:
        form_obj = forms.RegForm(request.POST)
        if form_obj.is_valid():
            # 只有执行了is_valid之后,才可执行cleaned_data,否则会报错
            # cleaned_data的数据是经过校验的
            print(form_obj.cleaned_data)
            return HttpResponse("注册成功!")
    return render(request, ‘register.html‘, {‘form‘: form_obj})

HTML文件:

<body>
{# novalidate:阻止验证(form组件会自动验证)#}
<form action="" method="post" novalidate>
    {% csrf_token %}
    <p>
        {{ form.phone.label }}
        {{ form.phone }}
        <span style="color: red">{{ form.phone.errors.0 }}</span>
    </p>
    <button>注册</button>
</form>
</body>

方式一(基本操作)

form文件:

from django import forms
from django.core.validators import RegexValidator

class RegForm(forms.Form):
    phone = forms.fields.CharField(
        label="手机号",
        validators=[
            RegexValidator(r‘^1[3-9]\d{9}$‘, "号码不合法")
            # RegexValidator(r"正则表达式", "错误提示信息")
        ],
    )

方式二(自定义验证规则)

form文件:

import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError

# 自定义验证规则
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 RegForm(Form):
    phone = fields.CharField(
        label="手机号",
        # 使用自定义验证规则
        # validators=[校验器函数1, 校验器函数2]
        validators=[mobile_validate, ],
        error_messages={‘required‘: "手机号不能为空", },
        widget=widgets.TextInput(
            attrs={‘class‘: ‘form-control‘, ‘placeholder‘: u"手机号码"},
        )
    )

方式三(利用钩子)

forms文件:

import re
from django.forms import Form
from django.forms import widgets
from django.core.exceptions import ValidationError

class RegForm(Form):
    phone = forms.fields.CharField(
        label="手机号",
        error_messages={‘required‘: "手机号不能为空", },
        widget=widgets.TextInput(
            attrs={‘class‘: ‘form-control‘, ‘placeholder‘: u"手机号码"},
        )
    )

    def clean_phone(self):
        value = self.cleaned_data.get(‘phone‘)
        mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘)
        if  mobile_re.match(value):
            return value
        raise ValidationError("手机号不合法")

验证密码一致性

视图文件同上??

form文件:

from django.forms import Form
from django.core.validators import RegexValidator

class RegForm(Form):
    pwd = forms.CharField(
        label="密码",
        min_length=6,
        widget=widgets.PasswordInput(),
    )
    re_pwd = forms.CharField(
        label="确认密码",
        min_length=6,
        widget=widgets.PasswordInput(),
    )

    def clean_re_pwd(self):
        pwd = self.cleaned_data.get(‘pwd‘)
        re_pwd = self.cleaned_data.get(‘re_pwd‘)
        if pwd == re_pwd:
            return re_pwd
        raise ValidationError("密码不一致")

HTML文件:

<body>
{# novalidate:阻止验证(form组件会自动验证)#}
<form action="" method="post" novalidate>
    {% csrf_token %}
    {# {{ form.as_p }}  以p标签的形式自动生成 #}
    <p>
        {{ form.pwd.label }}
        {{ form.pwd }}
        <span style="color: red">{{ form.pwd.errors.0 }}</span>
    </p>
    <p>
        {{ form.re_pwd.label }}
        {{ form.re_pwd }}
        <span style="color: red">{{ form.re_pwd.errors.0 }}</span>
    </p>
    <button>注册</button>
</form>
</body>


钩子


局部钩子

from django.forms import Form

class RegForm(Form):
    test01 = forms.CharField()

    test02 = forms.CharField()

    test03 = forms.CharField()

    # 局部钩子
    def clean_test02(self):
        test01 = self.cleaned_data.get(‘test01‘)
        test02 = self.cleaned_data.get(‘test02‘)
        test03 = self.cleaned_data.get(‘test03‘)
        print(test01, test02, test03)  # test03的值定会为None
        return test02

    """
    这里定义的是test02的钩子
    ! 定义哪个字段的钩子,就得返回哪个字段的值
    此时的钩子只能获取test01与test02的值,而test03的值为None
    因为test03字段在test02字段的下面,所以test02的钩子无法获取test03的值(更多可看源码)
    """

全局钩子

from django.forms import Form

class RegForm(Form):
    test01 = forms.CharField()

    test02 = forms.CharField()

    test03 = forms.CharField()

    # 全局钩子
    def clean(self):
        test01 = self.cleaned_data.get(‘test01‘)
        test02 = self.cleaned_data.get(‘test02‘)
        test03 = self.cleaned_data.get(‘test03‘)
        print(test01, test02, test03)
        return self.cleaned_data

    """
    这里定义的是全局钩子
    ! 定义全局钩子, 要返回self.cleaned_data的数据
    此时的钩子可以获取所有字段的值
    """


进阶


批量添加样式

通过重写form类的init方法来实现.

from django.forms import Form

class RegForm(Form):
    test01 = forms.CharField()
    test02 = forms.CharField()
    test03 = forms.CharField()

    def __init__(self, *args, **kwargs):
        super(RegForm, self).__init__(*args, **kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update(
                {
                    ‘class‘: ‘form-control‘,
                    ‘placeholder‘: "test",
                }
            )

ModelForm

form 与 model 的终结结合

==结合后将使用数据库字段的规则==

from django import forms

class BookForm(forms.ModelForm):

    class Meta:
        model = models.Hobby
        fields = ‘__all__‘
        labels = {
            ‘name‘: "爱好",
        }
        widgets = {
            ‘password‘: forms.widgets.PasswordInput(
                # attrs={}
            )
        }

"""
class Meta常见参数如下:

model = models.Student  # 对应的Model中的类
fields = "__all__"  # 字段,如果是__all__,就是表示列出所有的字段;如果是列表, 则只使用列表内的字段
exclude = []  # 排除的字段
labels = None  # 提示信息
help_texts = None  # 帮助提示信息
widgets = None  # 自定义插件
error_messages = None  # 自定义错误信息
"""

Form套Form

视图文件:

# 生成每行可编辑的form套form的表单
from django.forms import modelformset_factory  

def study_record(request, course_id):
    FormSet = modelformset_factory(models.StudyRecord, StudyRecordForm, extra=0)
    # 会自动在表单下面多生成一个form > extra=0:不生成
    queryset = models.StudyRecord.objects.filter(course_record_id=course_id)
    form_set = FormSet(queryset=queryset)
    return render(request, ‘crm/sutdy_record_list.html‘, {‘form_set‘: form_set})

HTML文件:

{% for form in form_set %}
    <tr>
        {{ form.id }}
        <td style="display: none">{{ form.student }}</td>
        {# style="display: none" 可禁用编辑#}
        <td>{{ forloop.counter }}</td>
        <td>{{ form.instance.student.name }}</td>
        <td>{{ form.attendance }}</td>
        <td>{{ form.score }}</td>
        <td>{{ form.homework_note }}</td>
    </tr>
{% endfor %}


【Django】Form组件

原文地址:https://www.cnblogs.com/zyk01/p/10176329.html

时间: 2024-10-03 22:54:47

【Django】Form组件的相关文章

Django ==&gt; Form 组件

Django ==> Form 组件 目录: 1.基本使用 2.form中字段和插件 3.自定义验证规则 4.动态加载数据到form中 Action: 1.基本使用 django 中的Form组件有一下功能: 1.生成html标签 2.验证用户数据(显示错误信息) 3.html form 提交保留上次提交数据 4.初始化页面显示内容 要使用 form 类,首先需要创建这个类,方法如下: from django.forms import Form from django.forms import

17 Django Form组件

目录 一.Form 介绍 二.注册功能校验数据案例 1.普通方式手写注册功能 2. 使用Form组件实现注册功能校验数据 三.Form组件如何校验数据 四.Form组件如何渲染前端页面 方式一: 方式二: 方式三: 五.Form组件如何展示错误信息 六.Form组件 参数 七.Form组件 钩子函数 1. 局部钩子函数 2. 全局钩子函数 一.Form 介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多

[oldboy-django][2深入django]Form组件功能: 数据格式验证 + 保留上次输入的值(如果有很多输入项,这样正确项不必重复输入,错误项也能提示错误信息)

1 需求:登录或者注册页面存在以下问题 - 无法记住上次提交的内容,(如果有很多输入项,这样正确项不必重复输入,错误项也能提示错误信息)- 重复进行提交数据的校验(数据是否为空,长度大小等等) 2 django的Form组件实现 2.1 Form组件实现数据验证方法 2.1.1 流程操作 - 定义规则(数据的格式,字段必须和表单上name属性一致) class LoginForm(Form): 字段名 = fields.xxFields(参数) # 定义了一个输入框的数据格式要求 实例化对象ob

Django——form组件

之前我们已经学习了HTML中的基本标签--form表单,我们经常使用它向后台提交数据,常规的form表单是这样的: <form action="" method="post"> <p>用户名:<input type="text" name="user"></p> <p>密码:<input type="text" name="pwd&

django form组件扩展

1简单扩展 利用form组件自带的正则扩展: a.方式一 from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.CharField( error_messages={'invalid': '...

Django form组件 与 cookie/session

目录 一.form组件 二.cookie.session 一.form组件 1.1 以注册功能为例 注册功能 1.渲染前端标签获取用户输入 --> 渲染标签 2.获取用户输入传递到后端校验 --> 校验数据 3.校验未通过展示错误信息 --> 展示信息 ps:校验数据:前后端都可以校验,但是前端可以不做,后端必须得做!!! 1.2 校验数据 校验数据 第一步需要一个form类 from django import forms class MyForm(forms.Form): name

Django Form组件实例:登录界面[Form表单提交,Ajax提交]

"""本例中使用Form和Ajax进行了数据提交,Form提交有一个问题,就是输入错误的数据,刷新之后原有的数据会丢失.注意到Form组件可以生成HTML标签,将Form生成的对象传到前端,就可以保留原有的内容,具体见下文:""" 1 from django.shortcuts import * 2 from app02 import models 3 import json 4 5 # Create your views here. 6 def

9.Django form组件

Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 创建Form类时,主要涉及到 [字段] 和 [插件],字段用于对用户请求数据的验证,插件用于自动生成HTML; 1.内置字段 Field required=True, 是否允许为空 widget=None, HTML插件 label=None, 用于生成Label标签或显示内容 initial=None, 初始值 help_tex

django Form组件 上传文件

上传文件 注意:FORM表单提交文件要有一个参数enctype="multipart/form-data" 普通上传: urls: url(r'^f1/',views.f1), url(r'^f2/',views.f2), views: def f1(request): if request.method == "GET": return render(request,'f1.html') else: import os #导入os模块 #request.get /

Django——form组件is_valid校验机制

#先来归纳一下整个流程#(1)首先is_valid()起手,看seld.errors中是否值,只要有值就是flase#(2)接着分析errors.里面判断_errors是都为空,如果为空返回self.full_clean(),否则返回self._errors#(3)现在就要看full_clean(),是何方神圣了,里面设置_errors和cleaned_data这两个字典,一个存错误字段,一个存储正确字段.#(4)在full_clean最后有一句self._clean_fields(),表示校验