一、forms组件使用  

  form django import forms

  1  自定义一个类,类需要继承forms.Form 

      自定义类的字段   映射   模板(html)中的form表单中的各种标签

 

  2. 模板利用 RegForm类的实例对象 form_obj进行渲染:

      自定义类RegForm的属性 CharField字段    映射   form表单的input标签

      

      

      

 

      1. form_obj.as_p --> 简单演示
      2.  form_obj.username         --> input标签
        form_obj.username.label      --> label名称(即label标签)
        form_obj.username.id_for_label  --> label标签for属性使用的id
        form_obj.errors          --> 用ul标签把所有的错误展示出来
        form_obj.username.errors.0     --> 取具体某个input标签(即RegForm属性字段)的第一个错误提示信息


  3. 视图views.py:
      1. 实例化
      form_obj = RegForm(request.POST)
      2. 数据有效性校验
        form_obj.is_valid()
          - true 表示数据没有问题
          - form_obj.cleaned_data --> 保存经过校验的数据的大字典

    类示例:

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


class RegForm(forms.Form):
    username = forms.CharField(
        min_length=2, max_length=8, label='用户名',
        error_messages={'min_length': '用户名不得少于2位', 'max_length': '用户名不得超过8位',
                        'required': '用户名不能为空'},
        widget=forms.widgets.TextInput(
            attrs={'class': 'form-control', 'placeholder': '请输入用户名'}
        )
    )

    password = forms.CharField(
        label='密码', error_messages={'required': '密码不能为空'},
        widget=forms.widgets.PasswordInput(
            attrs={'class': 'form-control', 'placeholder': '请输入密码'},
            render_value=True
        )
    )

    re_pwd = forms.CharField(
        label='确认密码', error_messages={'required': '确认密码不能为空'},
        widget=forms.widgets.PasswordInput(
            attrs={'class': 'form-control', 'placeholder': '请重复密码'},
            render_value=True

        )
    )

    phone = forms.CharField(
        label='手机号', error_messages={'required': '手机号不能为空'},
        validators=[RegexValidator(r'1[3-9]\d{9}$'), ],
        widget=forms.widgets.TextInput(
            attrs={'class': 'form-control', 'placeholder': '请输入手机号'},
        )
    )

    gender = forms.ChoiceField(
        label='性别',
        choices=((1, ''), (2, ''), (3, '保密')),
        initial=3,
        widget=forms.widgets.RadioSelect(
            attrs={'class': 'list-inline'}
        )
    )
    hobby = forms.MultipleChoiceField(
        label='爱好',
        widget=forms.widgets.CheckboxSelectMultiple(
            attrs={'class': 'list-inline'}
        )
    )

    """
    forms组件ChoiceField字段的choices若写成动态的从数据库中取数据,由于是静态字段,那么forms会为了
    保证页面的加载速度,会把第一次取来的数据放进缓存里边,所以若此时数据库数据有改动,页面并不会随
    着动态的改动。我们可以有两种方式解决这个问题。
    """

    # 总结:静态字段,获取的值无法实时更新

    # 重写父类__init__()
    def __init__(self, *args, **kwargs):
        super(RegForm, self).__init__(*args, **kwargs)
        self.fields['hobby'].choices = models.Hobby.objects.all().values_list('id', 'name')

    # 把forms字段跟models绑定
    # from django.forms import models as form_model
    # 
    # hobby = form_model.ModelMultipleChoiceField(
    #     queryset=models.Hobby.objects.all().values_list(),
    #     label='爱好',
    #     widget=forms.widgets.CheckboxSelectMultiple(
    #         attrs={'class': 'list-inline'}
    #     )
    # )
forms.py各种示例
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>注册</title>
 6     <link rel="stylesheet" href="/static/css/bootstrap/bootstrap3.3.7-min.css">
 7 </head>
 8 <body>
 9 <div class="container col-md-4 col-md-push-3" style="margin-top: 80px">
10 
11     <form class="form-horizontal" action="{% url 'reg' %}" novalidate method="post">
12         {% csrf_token %}
13         <div class="form-group">
14             <label class="col-sm-3 control-label"
15                    for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
16             <div class="col-sm-9">
17                 {{ form_obj.username }}
18                 {{ form_obj.username.errors.0 }}
19             </div>
20         </div>
21         <div class="form-group">
22             <label class="col-sm-3 control-label"
23                    for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label>
24             <div class="col-sm-9">
25                 {{ form_obj.password }}
26                 {{ form_obj.password.errors.0 }}
27             </div>
28         </div>
29         <div class="form-group">
30             <label class="col-sm-3 control-label"
31                    for="{{ form_obj.re_pwd.id_for_label }}">{{ form_obj.re_pwd.label }}</label>
32             <div class="col-sm-9">
33                 {{ form_obj.re_pwd }}
34                 {{ form_obj.re_pwd.errors.0 }}
35             </div>
36         </div>
37         <div class="form-group">
38             <label class="col-sm-3 control-label"
39                    for="{{ form_obj.phone.id_for_label }}">{{ form_obj.phone.label }}</label>
40             <div class="col-sm-9">
41                 {{ form_obj.phone }}
42                 {{ form_obj.phone.errors.0 }}
43             </div>
44         </div>
45         <div class="form-group">
46             <label class="col-sm-3 control-label">{{ form_obj.gender.label }}</label>
47             <div class="col-sm-9" style="margin-top: 5px">
48                 {{ form_obj.gender }}
49             </div>
50         </div>
51         <div class="form-group">
52             <label class="col-sm-3 control-label">{{ form_obj.hobby.label }}</label>
53             <div class="col-sm-9" style="margin-top: 6px">
54                 {{ form_obj.hobby }}
55             </div>
56         </div>
57         <div class="form-group">
58             <div class="col-sm-push-4 col-sm-7">
59                 <button type="submit" class="btn btn-block btn-lg btn-success">注册</button>
60             </div>
61         </div>
62     </form>
63 
64 </div>
65 </body>
66 </html>
reg.html模板渲染
 1 from django.shortcuts import render, HttpResponse
 2 from formapp.forms import RegForm
 3 # Create your views here.
 4 
 5 
 6 def reg(request):
 7     form_obj = RegForm()
 8     if request.method == 'POST':
 9         form_obj = RegForm(request.POST)
10         if form_obj.is_valid():
11             return HttpResponse('注册成功')
12     return render(request, 'reg.html', {'form_obj': form_obj})
views.py视图

  forms组件ChoiceField字段的choices若写成动态的从数据库中取数据,那么forms会为了保证页面的加载速度,
  会把第一次取来的数据放进缓存里边,所以若此时数据库数据有改动,页面并不会随着动态的改动。我们可以
  有两种方式解决这个问题。

 

  参考:https://www.cnblogs.com/liwenzhou/p/9030211.html

 

  方式一: 重写父类__init__()   

    def __init__(self, *args, **kwargs):
        super(RegForm, self).__init__(*args, **kwargs)
        self.fields['hobby'].choices = models.Hobby.objects.all().values_list('id', 'name')
在RegFom类中重写父类__init__()

  方式二:绑定models

    # 把forms字段跟models绑定
    from django.forms import models as form_model

    hobby = form_model.ModelMultipleChoiceField(
        queryset=models.Hobby.objects.all().values_list(),
        label='爱好',
        widget=forms.widgets.CheckboxSelectMultiple(
            attrs={'class': 'list-inline'}
        )
    )
forms绑定models

 

 

二、forms 的各种校验方法

  一、校验器

    1.django内置正则校验

        from django.core.validators import RegexValidator

       validators=[RegexValidator(r'1[3-9]\d{9}$'), ],

    2.自定义方法

      def name_check(value):

        if '哒哒哒' in value:

          raise ValidationError("不符合社会主义核心价值观!")
        else:
          return value

      使用:

      validators=[ name_check,]

  二、局部钩子:clean_字段名() 方法

     def  clean_name(self):

        print("我看了源码,你应该会帮我执行这个方法!")
        value = self.cleaned_data.get("name")
        if "哒哒哒" in value:
           raise ValidationError("不符合社会主义核心价值观!")
        else:
           return value

     def clean_name(self):
          print("我看了源码,你应该会帮我执行这个方法!")
          value = self.cleaned_data.get("name")
          if "哒哒哒" in value:
              raise ValidationError("不符合社会主义核心价值观!")
          else:
              return value

      

  三、全局钩子:重写clean()方法

    校验两次密码是否一致

      def clean(self):
          print("我可是看过源码的人,我知道你肯定会执行这个方法!")
          # 重写父类的clean方法
          # 该clean方法, 在每个字段都校验通过之后才调用执行
          pwd = self.cleaned_data.get("pwd")
          re_pwd = self.cleaned_data.get("re_pwd")

          if re_pwd and re_pwd == pwd:
              # 确认密码和密码相同, 正常
              return self.cleaned_data
          else:
              # 确认密码和密码不同
              self.add_error('re_pwd', "两次密码不一致")
              raise ValidationError("两次密码不一致")

 

 

形参

*  收集(单参数)(位置参数)

** 收集(键值对)(关键字参数)

 

实参

* 按(单值)打散

**按(键值对)打散

 

 

 

ok

posted on 2018-08-09 13:38  kingon  阅读(141)  评论(0编辑  收藏  举报