Form组件使用

form组件

form组件的功能

  • 生产input标签
  • 对提交的数据进行校验
  • 提供错误提示

form组件中常用字段

# 查看所有字段可点进forms中,fields里面是所有字段,widgets是所有插件

CharField    # 生成input框,默认文本输入框
ChoiceField   # 选择框,默认是select单选下拉框
MultipleChoiceField # 多选框,默认是select下拉框。里面是选择的内容

注:想更改可以用已经写好的字段,也可以直接改widget
如:email = forms.CharField(label='邮箱',widget=EmailInput)将文本输入框改成了邮箱输入框。

字段参数

required=True,               是否允许为空
widget=None,                 HTML插件,改变input框中格式,如:从文本变成email
label=None,                  用于生成Label标签或显示内容
initial=None,                初始值,默认值,默认填在input框中
error_messages=None,         修改错误信息显示内容 {'required': '不能为空', 'invalid': '格式错误'}
                           键是对应的参数,值是想要显示的错误信息内容
validators=[],               自定义验证规则
disabled=False,              是否可以编辑
min_length:                  设置最小长度

# widget=forms.PasswordInput()      设置成密文
# widget=forms.RadioSelect()        设置单选框
# widget=CheckboxInput()        设置input选择框,应用:记住密码
# widget=forms.CheckboxSelectMultiple() 设置多选框

模板HTML文件

注:模板中使用方法都是不加括号的。

{{ form_obj.as_p }}    __>   生产一个个P标签  input  label,实际使用不使用这个
{{ form_obj.errors }}    ——》   form表单中所有字段的错误
{{ form_obj.username }}     ——》 一个字段对应的input框,实际使用中
{{ form_obj.username.label }}    ——》  该字段的中文提示
{{ form_obj.username.id_for_label }}    ——》 该字段input框的id
{{ form_obj.username.errors }}   ——》 该字段的所有的错误
{{ form_obj.username.errors.0 }}   ——》 该字段的第一个错误的错误
{{ form_obj.non_field_errors.0 }} ---》 所有字段以外的错误

使用form组件实现注册功能

  • views.py

    先定义一个RegForm类:

    from django import forms
    
    class RegForm(forms.Form)
      username = forms.CharField(label='用户名',min_length=6)
        pwd = forms.CharField(label='密码',widget=forms.PasswordInput)  # widget设置密文
        hobby = forms.MultipleChoiceField(choices=((1,'篮球'),(2,'足球'),(3,'双色球')))
        ## 使用get_字段名_display()方法,获取到choices后面显示的结果。
    
        error_messages={
                'required': '用户名是必填项',
                'min_length': '用户名长度不能小于6位'
            }   # form组件默认错误提示都是英文,可以通过这种方式自定义成中文。
    
    # min_length: 设置最小长度
    # widget=forms.PasswordInput  设置成密文
    # choice=((),()) 
  • 再写一个视图函数
    # 使用form组件实现注册方式
      def register(request):
          form_obj = RegForm()
          if request.method == 'POST':
              form_obj = RegForm(data=request.POST)
              if form_obj.is_valid(): # 对数据进行校验,返回值是True或False
                  # 校验成功  把数据插入数据中
                  # models.UserProfile.objects.create(**form_obj.cleaned_data)
                  return HttpResponse('注册成功')
          return render(request,'register.html',{'form_obj':form_obj})
  • html文件
    <form action="" method="post" novalidate>
        {% csrf_token %}
        <p>
          <label for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
            {{ form_obj.username }}
            {{ form_obj.username.errors.0 }}
      </p>
    </form>
  • 如果部分数据需要从数据库中获取,那么数据需要随时更新,但是py文件并不是每次都加载,只加载一次放到内存中,py文件从上到下加载,RegForm()这个类中的内容只加载一次存到内存中,视图函数使用时,只是实例化这个类,并不会重新加载。只有当程序重启时才会重新加载,那么数据库中如果更新,则无法获取到新的数据。想让数据时时更新
    # 手动定义一个__init__,只要类实例化就会执行一次__init__,时时查询
    def __init__(self,*args,**kwargs):
        super(RegForm,self).__init__(*args,**kwargs)  # 继承父类,执行父类方法,否则会丢失功能
        self.fields['hobby'].choices = models.Hobby.objects.values_list('id','name')
        # values_list 由id,name组成的一个个元组的列表
    
    # self.fields会拿到RegForm类中所有字段的对象,是一个有序字典,如下
    OrderedDict([
        ('username', <django.forms.fields.CharField object at 0x0000000004108C18>),
      ('pwd', <django.forms.fields.CharField object at 0x0000000004108F60>),
        ('hobby', <django.forms.fields.CharField object at 0x0000000004108978>)
    ])
    
    # 直接以下面方法写
    hobby = forms.ModelMultipleChoiceField(           # 多选框
            queryset=models.Hobby.objects.all(),
        )

form验证

内置校验

  • required=True
  • min_length
  • max_length

自定义校验器

class RegForm(forms.Form):  # 需要一个一个字段写
    username = forms.CharField(
        label='用户名',
        min_length=6,
        initial='张三',
        required=True,
        validators=[checkname], # 列表中填写自定义的校验器,会把字段的值自动传给校验器进行校验
        widget = forms.TextInput(attrs={...})
        # attrs定义标签属性

        error_messages={
            'required': '用户名是必填项',
            'min_length': '用户名长度不能小于6位'
        }
    )
    gender = forms.ChoiceField(choices=[(1,'男'),(2,'女')])   # 单选
# 方式一:要定义一个函数
from django.core.exceptions import ValidationError
def checkname(value):   # 传的值就是字段要提交的数据,对value进行校验就行了
    # 通过校验规则 不做任何操作
    # 不通过校验规则   抛出异常
    if 'alex' in value:
        raise ValidationError('不符合社会主义核心价值观')

# 方式二:内置的校验器
from django.core.validators import RegexValidator   # 导入模块,正则校验
   # validators还有一些其他格式的校验器

class RegForm(forms.Form):
    phone = forms.CharField(
        validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式不正确')]
    )
# RegexValidator(),第一个参数写正则表达式,第二个参数写错误提示

钩子函数

  • 什么叫钩子:
  • 其主要思想是提前在可能增加功能的地方埋好(预设)一个钩子,这个钩子并没有实际的意义,当我们需要重新修改或者增加这个地方的逻辑的时候,把扩展的类或者方法挂载到这个点即可。
  • 局部钩子
    def clean_username(self):
        # 局部钩子,对单独一个字段进行校验
        # 通过校验规则  必须返回当前字段的值
        # 不通过校验规则   抛出异常
        v = self.cleaned_data.get('username')  # 能走到局部钩子,cleaned_data中就有值了,不然无法通过内置校验器和自定义校验器
        if 'alex' in v:
            raise ValidationError('不符合社会主义核心价值观')
        else:
            return v
  • 全局钩子
    def clean(self):
        # 全局钩子,对多个字段进行校验
        # 通过校验规则  必须返回当前所有字段的值
        # 不通过校验规则   抛出异常   '__all__'
        # 如果重写clean方法,必须写_validate_unique = True,不然不会校验字段的唯一性
        # 会检查model中的unique的限制
        self._validate_unique = True
        pwd = self.cleaned_data.get('pwd')
        re_pwd = self.cleaned_data.get('re_pwd')
    
        if pwd == re_pwd:
            return self.cleaned_data
        else:
            self.add_error('re_pwd','两次密码不一致!!!!!')  # 将错误信息添加到错误字典
            raise ValidationError('两次密码不一致')

is_valid的校验流程

#### is_valid的流程:执行is_valid()的流程
1.先执行full_clean()的方法:
    - 定义错误字典
    - 定义存放清洗数据的字典
2.执行_clean_fields方法:
    - 循环所有的字段
    - 获取当前的值
    - 进行校验 ( 内置校验规则   自定义校验器)
        1. 通过校验
            self.cleaned_data[name] = value
            - 如果有局部钩子,执行进行校验:
                - 通过校验——》 self.cleaned_data[name] = value
                - 不通过校验——》
                    self._errors  添加当前字段的错误 并且 self.cleaned_data中当前字段的值删除掉
        2. 没有通过校验
            self._errors  添加当前字段的错误
3.执行全局钩子clean方法

# 最终的判断就是错误字典中是否有值

ModelForm

  • 使用方法

    ########form组件使用步骤############
    1.先导入forms模块
    2.写类,继承forms.ModelForm
    3.在类中再写元类Meta
    4.在Meta中写字段model,代表根据哪个Model生字段,---》model = models.UserProfile
                                                  # UserProfile是创建表的类名
    5.字段fields,表示生成此Model中的哪些字段。__all__表示所有字段都生成,fields = '__all__';
      单独生成某几个字段
    6.如果表中没有的字段,可在类下创建
    
    ###########代码如下################
    
    from django import forms
    from app名称 import models
    from django.core.exceptions import ValidationError
    
    class RegForm(forms.ModelForm)
    # 与继承forms.Form的区别在于,forms.Form要在类中写每一个需要创建的input框
    # forms.ModelForm不需要每个都写,会根据某一个Model具体的生成每一个字段
    
      password = forms.CharField(widget=forms.PasswordIput('placeholder':'您的密码')) # 重写样式
      re_password = forms.CharField(widget=forms.PasswordIput('placeholder':'再次输入密码'))
    
        def __init__(self,*args,**kwargs):
            super().__init__(*args,**kwargs)
            # 限制当前新增客户为当前访问客户
            self.fields['customer'].choices = [(self.instance.customer.pk,self.instance.customer)]
    
        # 表中没有的字段可在Meta类下创建
      class Meta:
            model = models.UserProfile    # 根据哪个Model生成字段,UserProfile是创建表的类名
            fields = '__all__'    # 生成表中的哪些字段,'__all__'是生成所有的
            # 填写指定字段['username','password']
    
            exclud = ['is_active']    # 排除is_active字段
            widgets = {       # 字典内写上指定字段的名字
                'username':forms.TextInput(attrs={'placeholder':'您的用户名','autocomplete':'off'})
            }
            # autocomplete表示填写记录
            # 可以对表中的所有字段样式,进行修改
            # attrs中写想要更改的相关属性
    
            error.messages = {        # 错误信息
                'username':{
                    'required':'必填'      # 必填
                    'invalid':'请输入正确邮箱地址' # 格式错误
                }
            }
            # 在settings配置文件中将LANGUAGE_CODE = 'zh-Hans'
        def clean(self):
            password = self.cleaned_data.get('password',"")
            # 当都不填时会返回None在加密时报错,所以让他获取不到password时获取一个空字符串
    
            re_password = self.cleaned_data.get('re_password',"")
            if password == re_password:
                # 对密码进行加密
                md5 = hashlib.md5()
                md5.update(password.encode('utf-8'))
                self.cleaned_data['password'] = md5.hexdigest()
                return self.cleaned_data
            else:
                self.add_error('re_password', '两次密码不一致')
                raise ValidationError('两次密码不一致!!')
    
    ######视图函数######
    def reg(request): # 视图函数
        form_obj = RegForm()
        if request.method == 'POST':
            form_obj = RegForm(request.POST)
            if form_obj.is_valid():
                form_obj.save()
              return redirect(reverse('login'))
        return render(request,'reg.html',{'form_obj':form_obj})
    
    #######模板语法#######
    
    <form action='' ,method='post' novalidate>
    # novalidate 不在前端进行校验,前端写的校验会失效
        {% for field in form_obj %}
            <div class="form-group {% if field.errors %}has-error{% endif %}">
                <label {% if not field.field.required %} style="color: #777777" {% endif %} for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label>
                <div class="col-sm-8">
                    {{ field }}
                    <span class="help-block">{{ field.errors.0 }}</span>
                </div>
            </div>
        {% endfor %}
    
          {{ form_obj.errors }}    ——》   form表单中所有字段的错误
        {{ form_obj.username }}     ——》 一个字段对应的input框,一般使用这个一个个input创建
        {{ form_obj.username.label }}    ——》  该字段的中文提示
        {{ form_obj.username.id_for_label }}    ——》 该字段input框的id
        {{ form_obj.username.errors }}   ——》 该字段的所有的错误
        {{ form_obj.username.errors.0 }}   ——》 该字段的第一个错误的错误
        {{ form_obj.non_filed_errors }}     ——》   # __all__的错误,不限于表单中
    </form>
  • 更改input框的中文名显示方式
    1.创建表时填写verbose_name属性,值为想要显示的中文名
    2.在常见input框时有label标签,可以显示中文

modelformset_factory

  • modelformset_factory会先创建一个类,参数有model,Form类,extra

    • model:模型,表的类名
    • Form:form表单的类名
    • extra:默认为1,未添加数据是显示一条空数据,设置为0则可不设置该条空数据
    ModelFormSet = modelformset_factory(models.StudyRecord, StudyRecordForm, extra=0)
    def study_record_list(request, course_record_id):
        ModelFormSet = modelformset_factory(
            models.StudyRecord, StudyRecordForm, extra=0)
        form_set_obj = ModelFormSet(queryset=models.StudyRecord.objects.filter
                                    (course_record_id=course_record_id))
        if request.method == 'POST':
            form_set_obj = ModelFormSet(queryset=models.StudyRecord.objects.filter
                                        (course_record_id=course_record_id),data=request.POST)
            if form_set_obj.is_valid():
                form_set_obj.save()
    
                return HttpResponse('保存成功')
    
        return render(request, 'teacher/study_record_list.html', {'form_set_obj': form_set_obj})
  • 模板中
    <!--文本不可修改的内容用该方式取-->
    <td>{{ form.instance.student }}</td>
    // form.instance 是一个对象
    // form.instance.student  通过对象拿到其中的字段值
    
    <!--在模板中使用-->
    在form标签下必须添加如下内容,固定写法
    {{ form_set_obj.management_form }}  <!--会生成4个隐藏标签-->
    <input type="hidden" name="form-TOTAL_FORMS" value="2" id="id_form-TOTAL_FORMS">
    <input type="hidden" name="form-INITIAL_FORMS" value="2" id="id_form-INITIAL_FORMS">
    <input type="hidden" name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS">
    <input type="hidden" name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS">
    
    在循环创建form表单时,再循环下加{{ form.id }},用来标识form表单,目的找对应的对象,生成隐藏input标签
    <input type="hidden" name="form-1-id" value="2" id="id_form-1-id">
    
    <!--代码示例-->
    <form action="" method="post">
        {% csrf_token %}
        {{ form_set_obj.management_form }}
        <table class="table table-bordered table-hover">
            <thead>
            <tr>
                <th>序号</th>
                <th>学生</th>
                <th>考勤</th>
                <th>成绩</th>
                <th>作业批语</th>
            </tr>
            </thead>
            <tbody>
            {% for form in form_set_obj %}
                <tr>
                    {{ form.id }}
                    <td>{{ forloop.counter }}</td>
                    <td>{{ form.instance.student }}</td>
                    <td>{{ form.attendance }}</td>
                    <td>{{ form.score }}</td>
                    <td>{{ form.homework_note }}</td>
                    <td class="hidden">{{ form.student }}</td>
                    <td class="hidden">{{ form.course_record }}</td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
        <button class="btn btn-primary">保存</button>
    </form>

原文地址:https://www.cnblogs.com/liuweida/p/12303066.html

时间: 2024-10-14 23:41:19

Form组件使用的相关文章

Django框架之Form组件

新手上路 From组件的主要功能: 1,对form表单提交的数据进行校验. 内部基于正则进行匹配 2,from表单提交保存上次提交的数据. 生成HTML标签 初入大荒 1,创建Form类 class StudentForm(Form): #字段名,最好跟数据库内的字段名一样,好操作 #如CharField,内部包含了正则表达式, name = fields.CharField(max_length=12, min_length=2, required=True, widget=widgets.T

小而美的 React Form 组件

背景 之间在一篇介绍过 Table 组件< React 实现一个漂亮的 Table > 的文章中讲到过,在企业级后台产品中,用的最多且复杂的组件主要包括 Table.Form.Chart,在处理 Table 的时候我们遇到了很多问题.今天我们这篇文章主要是分享一下 Form 组件,在业务开发中, 相对 Table 来说,Form 处理起来更麻烦,不是所有表单都像注册页面那样简单,它往往需要处理非常多的逻辑,比如: 需要处理数据验证逻辑. 在一个项目中的很少有可以复用的表单,每个表单的逻辑都需要

form组件相关 -新 -转

Mr.Seven 博客园 首页 新随笔 联系 订阅 管理 随笔-126  文章-137  评论-268 Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建Form类 from django.forms import Form from django.forms import widgets from django.forms import fiel

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 /

Python之路【第二十一篇】:Django之Form组件

Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建Form类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from django.forms import Form from django.forms import widgets from django.forms imp

Django框架基础之Form组件

服务端假设所有用户提交的数据都是不可信任的,所以Django框架内置了form组件来验证用户提交的信息 form组件的2大功能:       1 验证(显示错误信息)       2 保留用户上次输入的信息                  -- 可以生成html标签应用: class A_Form(Form): 字段=fields.字段类型(默认参数: required=True, widget=widgets.插件(attrs={})) 常用字段:Charfield,RegexField,I

认证登录装饰器与form组件的使用

def auth(func): '''制作登录认证的装饰器''' def inner(request,*args,**kwargs): user_info=request.session.get(settings.SJF) if not user_info: return redirect('/login/') return func(request,*args,**kwargs) return inner ''' form组件的使用 1.用户请求数据验证 2.自动生成错误信息 3.打包用户提交

form组件

一.form组件    1.- Form组件             - 创建类,继承Form            - 创建字段,字段=正则表达式: PS: 字段名称,required,  error_messages = {required,invalid}            - form = MyForm(data=request.POST)            - form.is_valid()            - form.cleaned_data            -

django 之知识点总结以及Form组件

一.model常用操作 1.13个API查询:all,filter,get ,values,values_list,distinct,order_by ,reverse , exclude(排除),count,first,last,esits(判断是否存在) 需要掌握的all.values.values_list的区别 all:打印的是一个QuerySet集合,一个列表里面放的对象 values :是一个字典形式 values_list:是一个元组形式 all的性能是最低的 2.only和def

django补充和form组件

Model常用操作: - 参数:filter - all,values,values_list [obj(id,name,pwd,email),obj(id,name,pwd,email),] models.UserInfo.objects.all() [obj(id,name,email)] # pwd未取值 data_list = models.UserInfo.objects.all().only('name','email') for item in data_list: item.id