django—Form组件

  django的Form组件主要实现的功能:

    1、渲染html代码(不用手写相关前端表单代码)

    2、校验数据

    3、展示提示信息

Form组件的定义

  以注册功能为例

  from django import forms
  class RegForm(forms.Form):
   user = forms.CharField()
  pwd = forms.CharField()

  一个功能的form组件是一个类,这个类必须继承forms中的Form类(和模型类定义的形式有点类似);

  这个类内部定义的成员变量就对应着前端页面的一个个input标签。

 

Form组件的基本使用

  1、在视图函数中

    def reg(request):
    form_obj = RegForm()
    return render(request, 'reg.html', {'form_obj': form_obj})

    只需要将Form类实例化,传给对应的前端页面完成渲染,即可展示相应的表单内容

  2、在模板文件中渲染

    由于form组件只提供表单内部的元素,不包含表单以及按钮。所以在模板文件中需要手写相关代码。

    <form action="" method="post">
    {% csrf_token %}
    {{ form_obj.as_p }}
    <button>注册</button>
    </form>

    以上代码在前端显示为

    

 

 

     form_obj.as_p:将每个元素以p标签形式渲染出来(p标签内部有label和input)

    

  3、标签渲染的方式

    a、以不同形式,自动将所有元素一次性渲染出来,不利于后续扩展。

     {{ form_obj.as_p }}

     {{ form_obj.as_ul }}

     {{ form_obj.as_table }} 

    b、根据from_obj内部的成员变量,手动生成想要的元素以及展示形式,扩展性高,代码冗余。

     <p>{{ form_obj.user.label }}:{{ form_obj.user }}</p>

     <p>{{ form_obj.pwd.label }}:{{ form_obj.pwd }}</p>

    c、利用for循环生成元素,扩展性高,代码精简。

     {% for form in form_obj %}

      <p>{{ form.label }}:{{ form }}</p>

     {% endfor %}

 

  4、校验数据

    后端要想使用Form组件进行数据的校验,首先需要关闭前端的校验(直接将数据给后端)

    只需要在from标签内加上novalidate属性即可

    后端校验数据:

    def reg(request):
    form_obj = RegForm() # 空的Form对象
    if request.method == 'POST':
    form_obj = RegForm(request.POST) # 包含用户提交的数据的From对象
    if form_obj.is_valid(): # 对数据进行校验
    return HttpResponse('ok')
    # 如果校验不成功,那么render返回的form_obj中就包含了对应字段的错误信息,可以渲染在前端
    return render(request, 'reg.html', {'form_obj': form_obj})

    前端可以通过{{ form_obj.errors }}打印出所有的错误,也可以根据不同字段来打印错误信息{{ form_obj.user.errors }}

    如果某个字段有多个错误还可以通过下标的方式选择打印错误信息{{ form_obj.user.errors.0 }},否则是以列表的形式展示数据

    

    form组件会在数据不合法的情况下,保存上次的数据,让用户基于上次的数据进行修改。

Form常用的字段和参数

  1、常用字段

    Form组件可用的字段有:

    __all__ = (
    'Field', 'CharField', 'IntegerField',
    'DateField', 'TimeField', 'DateTimeField', 'DurationField',
    'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField',
    'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
    'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
    'SplitDateTimeField', 'GenericIPAddressField', 'FilePathField',
    'SlugField', 'TypedChoiceField', 'TypedMultipleChoiceField', 'UUIDField',
    )   

    CharField——文本输入框

    EmailField——邮箱文本输入框(输入的字段必须符合邮箱的格式)

    ChoiceField——单选框 默认是select

    MultipleChoiceField——多选框 默认是select

  2、字段参数

    initial——设置默认值

    error_messages——重写错误信息(默认错误信息是固定格式且是英文的) 

      error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
         }

      也可以不设置error_messages,直接将settings里的LANGUAGE_CODE设置成'zh-hans',这样所有错误信息都可以中文显示

    label——设置字段名,前端默认展示的字段名是首字母大写的成员变量名

    choices——设置选择框的选项,每个选项都以元组形式存储(存储在数据库的值,前端页面展示的值)

    required——设置字段是必填项

    disabled——设置input是否禁用

    validators——设置字段的校验器,对应值是一个列表,列表内存放函数对象,即相关校验函数。

    widget——插件,修改input的类型    

      widget=forms.PasswordInput(attrs={'class':'form-control c1 c2'})

      修改input类型的同时还能够设置属性值

      可选的类型如下:   

        __all__ = (
        'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'NumberInput',
        'EmailInput', 'URLInput', 'PasswordInput', 'HiddenInput',
        'MultipleHiddenInput', 'FileInput', 'ClearableFileInput', 'Textarea',
        'DateInput', 'DateTimeInput', 'TimeInput', 'CheckboxInput', 'Select',
        'NullBooleanSelect', 'SelectMultiple', 'RadioSelect',
        'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget',
        'SplitHiddenDateTimeWidget', 'SelectDateWidget',
        )

      通过修改CharField的类型,可以实现其他字段的效果。

          

  补充:

    前端展示选择框数据的时候,往往这些数据都是写死的。

    可以将选择框数据单独存放在表中,然后将该表的查询结果作为展示数据,这样前端展示选择框数据时就可以实现动态展示。

      首先需要导入   from django.forms import models  as form_model

        hobby = form_model.ModelMultipleChoiceField( queryset=models.Hobby.objects.all(), widgets=forms.CheckboxSelectMultiple)

 

校验方法

  1、设置校验器

    定义校验函数

    from django.core.exceptions import ValidationError
    def check_name(value):
    if '1' in value:
    raise ValidationError('该用户名不符合要求')

    在相应字段加上validators参数

    user = forms.CharField(label='用户名', validators=[check_name])

    校验函数内,出现不符合校验标准的情况必须抛出ValidationError异常,异常信息作为校验错误的提示信息

    

 

 

   2、定义钩子函数

    钩子函数需要定义在Form类当中

    a、局部钩子

      函数的命名为clean_字段名

      class RegForm(forms.Form):
      user = forms.CharField(label='用户名')
      pwd = forms.CharField(label='密码', widget=forms.PasswordInput())

      def clean_user(self):
      value = self.cleaned_data.get('user')
      if '1' in value: # 不符合校验规则
      raise ValidationError('该用户名不符合要求')
      # 符合校验规则
      return value

      cleaned_data是经过is_valid()校验过,没有问题的数据字典

      使用is_valid()方法前,没有cleaned_data字典,获取时会报错

      只有在is_valid()方法之后,才生成了cleaned_data字典

    b、全局钩子

      全局钩子命名为clean,针对所有字段

      def clean(self):
      username = self.cleaned_data.get('user')
      pwd = self.cleaned_data.get('pwd')
      if '1' in username: # 不符合校验规则
      raise ValidationError('该用户名不符合要求')
      if '1' in pwd:
      raise ValidationError('密码包含禁用词')
      # 符合校验规则 返回所有字段的值
      return self.cleaned_data

      此时,抛出的错误信息存放在全局{{ form_obj.errors }},不能通过字段名的错误信息获取到

      要想将错误信息存放在某个字段当中,可以通过以下方法:

        self.add_error(字段名,错误信息)

        self.add_error('pwd', '错误')

      注意:

        钩子函数中出现不符合校验规则的情况,必须要抛出异常。

        即便已经将某个错误信息存放到指定字段中,也需要抛出异常(固定搭配)

   

ModelForm

  ModelForm就是model和form的结合。

  原本在定义form类的时候,需要自己表单中的字段元素。

  有时候可以根据model类中定义好的字段来生成相应表单,如用户信息(账号密码)。

  1、定义 

  class RegForm(forms.ModelForm):
  
    class Meta:
     model = User
    fields = '__all__'
    widgets = {
      'username': forms.TextInput(attrs={'class': 'lowin-input'}),
    'pwd': forms.PasswordInput(attrs={'class': 'lowin-input'}),
    }
    error_messages = {
     'username': {
     'required': '用户名不能为空',
    'unique': '用户名已存在,请重新输入',
    },
    'pwd': {
     'required': '密码不能为空',
    },
    }

    class Meta中的参数说明: 

      model = models.User  # 对应的Model中的类
      fields = "__all__"  # 字段,如果是__all__,说明model类中的所有字段都将被用于生成表单
      exclude = None  # 排除的字段,排除掉的字段,不会生成在表单中
      labels = None  # 提示信息
      help_texts = None  # 帮助提示信息
      widgets = None  # 自定义插件
      error_messages = None  # 自定义错误信息

 

 

  2、使用方式和Form基本一致

    ModelForm对象有一个save方法,可以直接将接收到的有效数据保存到数据库中。

    前提的是:

      该ModelForm对象不是空对象,必须用接收到的数据初始化  

      form_obj = RegForm(request.POST)
      if form_obj.is_valid():
      form_obj.save()
      return HttpResponse('ok')

  3、调整form中字段显示的先后顺序

    在class Meta中,将fields的值改成列表,列表中字段的先后顺序,就是前端for循环的迭代的先后顺序

    如:

      fields = ['username', 'password', 're_password', 'mobile_phone', 'code']

 

posted @ 2020-07-19 00:19  yamx  阅读(184)  评论(0编辑  收藏  举报