Django中Form表单之字段详解

Django中的Form表单

  1、背景

    平时我们在书写form表单时,经常都是手动的去写一些input标签,让用户输入一些功能,进行一些校验的判断,等等。Django中的form表单就能够帮我们去实现这些功能,比较便捷。

  2、Django form表单的功能

      1、生成页面可执行的HTML标签

      2、对应户的数据进行校验

      3、保留上次输入的内容

  3、先用普通方式手写一个注册功能

    1、views.py文件中

复制代码
复制代码
# 注册
def register(request):
    error_msg = ""            # 刚进页面的时候,用户名还为空,此时错误信息先设置成空
    if request.method == "POST":
        username = request.POST.get("name")
        pwd = request.POST.get("pwd")
        # 对注册信息做校验
        if len(username) < 6:
            # 用户长度小于6位
            error_msg = "用户名长度不能小于6位"
        else:
            # 将用户名和密码存到数据库
            return HttpResponse("注册成功")
    return render(request, "register.html", {"error_msg": error_msg})
复制代码
复制代码

    2、register.html文件中

复制代码
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
<form action="/reg/" method="post">
    {% csrf_token %}
    <p>
        用户名:
        <input type="text" name="name">
    </p>
    <p>
        密码:
        <input type="password" name="pwd">
    </p>
    <p>
        <input type="submit" value="注册">
        <p style="color: red">{{ error_msg }}</p>
    </p>
</form>
</body>
</html>
复制代码
复制代码

  4、用form表单组件实现功能

    1、views.py文件中

      1、先定义一个RegForm类

复制代码
复制代码
from django import forms           # 导入forms 模块

# 按照Django form组件的要求自己写一个类
class RegForm(forms.Form):
    name = forms.CharField(label="用户名")      # 会给name前边生成一个lable标签
    pwd = forms.CharField(label="密码")        # 会给pwd前边生成一个lable标签
复制代码
复制代码

      2、写一个视图函数

复制代码
复制代码
# 使用form组件实现注册方式
def register2(request):
    form_obj = RegForm()         # 实例化一个对象
    if request.method == "POST":
        # 实例化form对象的时候,把post提交过来的数据直接传进去
        form_obj = RegForm(request.POST)
        # 调用form_obj校验数据的方法
        if form_obj.is_valid():
            return HttpResponse("注册成功")
    return render(request, "register2.html", {"form_obj": form_obj})    
复制代码
复制代码

    2、register2.html文件中

复制代码
复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-Type" charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>

<form action="" method="post" novalidate autocomplete="off">  # novalidate 关闭django form表单自带的一些校验机制,  autocomplete='off' 可以让输入框输入的数据保留下来,在刷新页面的时候不被清空
    {% csrf_token %}
{#        {{ form_obj.as_p }}           对象.as_p 生成p标签,里边会自动成成input标签#}
    <p> {{ form_obj.user.label }}       {# 生成 lable 标签 #}
        {{ form_obj.user }}             {# 生成 user 的 input 标签 #}
        <span style="color: red">{{ form_obj.user.errors.0 }}</span>   # form_obj.errors 是一个字典,通过.user拿到user这个键值对,
                                           # 再通过.error拿到一个django form 表单自动生成的<u>l标签下的<li>标签的错误信息,最后通过.0索引取到错误信息 </p> <p> {{ form_obj.pwd.label }} {{ form_obj.pwd }} <span style="color: red">{{ form_obj.pwd.errors.0 }}</span> </p> <p> {{ form_obj.re_pwd.label }} {{ form_obj.re_pwd }} <span style="color: red">{{ form_obj.re_pwd.errors.0 }}</span> </p
复制代码
复制代码

      form_obj.errors  类型  和 内容

    3、小结:

复制代码
复制代码
1、自动成成<pP标签和<input>的方法:
   {{ form_obj.as_p}}        # 自动生成<p>标签并且里边如果有属性会生成<input>标签



   {{ form_obj.user.lable}}   # 单独生成<lable>标签
    {{form_obj_user}}   # 单独生成一个输入用户名的<input> 标签
复制代码
复制代码
2if request.method == 'POST':
        form_obj = RegForm(request.POST)

#  给实例化的对象获取所有的POST请求的数据,这样就可以通过对象.属性拿值了
复制代码
复制代码
3
        if form_obj.is_valid():      # 通过is_valid方法,检验所有的POST请求提交的数据,如果有一个没通过校验,都无法将数据添加到cleaned_data中。
            # cleaned_data  是经过校验的数据
            print(form_obj.cleaned_data)
# form_obj.cleaned_data  的数据类型是个字典
# <class 'dict'> {'user': '22w1236', 'pwd': '123456', 're_pwd': '123456', 'phone': '1333333333'} 这是所有校验都通过后,cleaned_data字典中存的校验信息
复制代码
复制代码

  5、常用字段与插件

    1、initial

      设置初始值,也就是默认值

       

复制代码
复制代码
class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,   # 用户名最小长度为8
        label="用户名",
        initial="张三"  # 设置默认值
    )
    pwd = forms.CharField(min_length=6, label="密码")  # 密码最小长度为6
复制代码
复制代码

    2、error_messages

      自定义错误信息

复制代码
复制代码
class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密码")

# 如果不满足条件,就会按照错误类型,报出自定义的错误
复制代码
复制代码

    3、password

复制代码
复制代码
from django.forms import widgets
class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )

# widgets 是一个插件
#  widget=forms.widgets.PasswordInput()  将Input框的类型设置成password类型
复制代码
复制代码

    4、radioSelect

复制代码
复制代码
class LoginForm(forms.Form):
    gender = forms.fields.ChoiceField(
        choices=((1, ""), (2, ""), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )
#    gender = forms.fields.ChoiceField 先设置成ChoiceField 
#    通过插件widgests设置成单选框
复制代码
复制代码

    5、单选Select

复制代码
复制代码
class LoginForm(forms.Form):
    ...
    hobby = forms.fields.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )

# 通过widgest 插件 设置成单选下拉框
复制代码
复制代码

    6、多选Select

复制代码
复制代码
class LoginForm(forms.Form):
    ...
    hobby = forms.fields.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

# 通过插件widgets.SelectMultiple 设置成 多选下拉框
复制代码
复制代码

    7、单选checkbox

复制代码
复制代码
class LoginForm(forms.Form):
    ...
    keep = forms.fields.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

# 设置成复选框格式的单选
复制代码
复制代码

    8、多选checkbox

复制代码
复制代码
class LoginForm(forms.Form):
    ...
    hobby = forms.fields.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

# 设置成复选框的多选框
# 首先是 字段 = form.field.MultipleChoiceField
# 通过插件.CheckboxSelectMultiple 设置成复选框的多选框
复制代码
复制代码

    9、自定义初始化方法

     在使用选择标签的时候,也就是在指定有关于choices的那些选择框,里边的数据是可以从数据库中获取的,也就不需要手动去代码中添加,而是通过 models.Classes.objects.all().values_list('id','caption')就能够动态的将数据库中的相关信息添加到选项框中,但是他只能获取静态的值,当数据库中有新的数据更新进去的时候,就无法获取(相对的,如果重启一次服务也能获取到),这时就需要自定义一个初始化方法。

  

复制代码
复制代码
from django.forms import Form
from django.forms import widgets
from django.forms import fields

 
class MyForm(Form):
 
    user = fields.ChoiceField(
        # choices=((1, '上海'), (2, '北京'),),
        initial=2,
        widget=widgets.Select
    )
 
    def __init__(self, *args, **kwargs):          # 自定义一个__init__方法的初始化方法,通过调用父类的__iniy__方法,进行初始化实现动态更新
        super(MyForm,self).__init__(*args, **kwargs)
        # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
        # 或
        self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')    # 动态从数据库中获取值
复制代码
复制代码

  6、Django 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类型

Django Form内置字段
复制代码
复制代码

  7、校验

    1、正则校验RegexValidator

复制代码
复制代码
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(
        validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
], )
复制代码
复制代码

    2、ValidationError

复制代码
复制代码
from django.core.exceptions import ValidationError

    def clean_phone(self):
        value = self.cleaned_data.get('phone')
        if re.match(r'^1[3-9]\d{9}$',value):
            return value

        raise ValidationError('手机号不正经')
复制代码
复制代码

    3、局部钩子函数校验

复制代码
复制代码
 def clean_re_pwd(self):
        # 通过对象.cleaned_data.get(字段)获取字段信息,且注意顺序,确认密码必须写在密码之后,不然会造成,校验还没完成就去获取值,是获取不到的
        pwd = self.cleaned_data.get('pwd')     
        re_pwd = self.cleaned_data.get('re_pwd')

        if pwd == re_pwd:
            return re_pwd
        raise ValidationError('两次密码不一致')        
复制代码
复制代码

    4、全局钩子函数校验

复制代码
复制代码
    def clean(self):
        pwd = self.cleaned_data.get('pwd')
        re_pwd = self.cleaned_data.get('re_pwd')

        if pwd == re_pwd:
            return self.cleaned_data
        self.add_error('re_pwd','两次密码不一致')
        raise ValidationError('两次密码不一致')

#  定义全局钩子函数的时候,函数名必须是clean
#  全局钩子的特点是,先对所有的字段进行一次校验,然后再从校验的结果中,进行二次校验,返回一个cleaned_data
# 给校验的字段添加提示的错误信息,方法是 对象.add_error('字段名称','错误信息内容')
复制代码
复制代码

 

  

posted @   洪豆豆的记录  阅读(2376)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
点击右上角即可分享
微信分享提示