s4 form

- Form

    - 需要对请求数据做验证
    - 获取到数据然后进行验证    
    - 解决问题:
        - 重复进行用户数据校验:正则,长度,是否为空
        - 无法记住上次提交内容,刷新页面数据消失
    - 参考博客:
        http://www.cnblogs.com/wupeiqi/articles/6144178.html
    
    1. 定义规则
    
        from django.forms import Form
        from django.forms import fields
        class xxx(Form):
            xx = fields.CharField(required=True,max_lenght.,min,error_message=)

    2. 使用
    
        # 创建对象:
            obj = xxx(request.POST)
            
        # 是否校验成功
            v = obj.is_valid()
            # html标签name属性 == Form类字段名
            
        # 所有错误信息
            obj.errors
            # obj.errors['username][0]
            # 对象 __str__
        
        # 正确信息
            obj.cleaned_data
            # 字典
            
    3. 例子
    
        from django.forms import Form
        from django.forms import fields
        class LoginForm(Form):
            username=fields.CharField(
                max_length=18,
                min_length=6,
                required=True,
                error_messages={
                    'required':'不能为空',
                    'min_length':'不能小于6',
                    'max_length':'不能大于18',
                }
            )
            password=fields.CharField(min_length=16,required=True)

        def login(request):
            if request.method=="GET":
                return render(request,'login.html')
            else:
                obj=LoginForm(request.POST)
                if obj.is_valid():
                    print(obj.cleaned_data) #字典
                    return redirect('http://www.baidu.com')
                else:
                    # print(obj.errors)
                    #对象 __str__
                    return render(request,'login.html',{'obj':obj
                    
        <form action="/login/"method="POST">
            {% csrf_token %}
            <p>用户:<input type="text"name="username">{{ obj.errors.username.0 }}</p>
            <p> 密码:<input type="password"name="password">{{ obj.errors.password.0 }}</p>
            <input type="submit"value="提交">
        </form>

    
    - 内部原理
                            
        def login(request):
            if request.method == 'GET':
                return render(request,'login.html')
            else:
                obj = LoginForm(request.POST)
                # is_valid
                """
                1. LoginForm实例化时,
                    self.fields={
                        'user': 正则表达式
                        'pwd': 正则表达式
                    }
                2. 循环self.fields
                      flag = True
                      errors
                      cleaned_data
                      for k,v in self.fields.items():
                        # 1. user,正则表达式
                        input_value = request.POST.get(k)
                        正则表达式和input_value
                        flag = False
                      return flag
               """
                if obj.is_valid():
                    print(obj.cleaned_data)
                else:
                    print(obj.errors)
                return render(request,'login.html')    

    - 对用户提交的数据进行校验                            
    - 生成HTML标签    
    - 保留上次输入的内容
                
        
    - Form提交验证:(无法保留上次输入内容)
    
        class XXForm(Form):
            user = fields.CharField(min_length=8)
            email = fields.EmailField()
            password = fields.CharField()
            phone = fields.RegexField('139\d+')
        
        
        def login(request):
            if request.method == 'GET':
                return render(request,'login.html')
            else:
                obj = LoginForm(request.POST)
                if obj.is_valid():
                    print(obj.cleaned_data)
                    return redirect('http://www.baidu.com')
                return render(request,'login.html',{'obj': obj})
        
        <form id="f1" action="/login/" method="POST">
            {% csrf_token %}
            <p><input type="text" name="user" />{{ obj.errors.user.0 }}</p>
            <p><input type="password" name="pwd" />{{ obj.errors.pwd.0 }}</p>
            <input type="submit" value="提交" />
        </form>
        
            
    - Ajax提交验证:
        
        class XXForm(Form):
            user = fields.CharField(min_length=8)
            email = fields.EmailField()
            password = fields.CharField()
            phone = fields.RegexField('139\d+')
        
        
        def ajax_login(request):
            import json
            ret = {'status': True,'msg': None}
            obj = LoginForm(request.POST)
            if obj.is_valid():
                print(obj.cleaned_data)
            else:
                # print(obj.errors) # obj.errors对象
                ret['status'] = False
                ret['msg'] = obj.errors
            v = json.dumps(ret)
            return HttpResponse(v)
            

        <form id="f1" action="/login/" method="POST">
            {% csrf_token %}
            <p><input type="text" name="user" /></p>
            <p><input type="password" name="pwd" /></p>
            <input type="submit" value="提交" />
            <a onclick='submitForm():'>提交</a>
        </form>

        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            function submitForm(){
                $('.c1').remove();
                $.ajax({
                    url: '/ajax_login/',
                    type: 'POST',
                    data: $('#f1').serialize(),// user=alex&pwd=456&csrftoen=dfdf\
                    dataType:"JSON",
                    success:function(arg){
                        console.log(arg);
                        if(arg.status){

                        }else{
                            $.each(arg.msg,function(index,value){
                                console.log(index,value);
                                var tag = document.createElement('span');
                                tag.innerHTML = value[0];
                                tag.className = 'c1';
                                $('#f1').find('input[name="'+ index +'"]').after(tag);
                            })
                        }
                    }
                })
            }
        </script>

        
    - 保留Form上次输入内容
    

        - 例子:
            class RegisterForm(Form):
                user = fields.CharField(min_length=8)
                email = fields.EmailField()
                password = fields.CharField()
                phone = fields.RegexField('139\d+')


            def register(request):
                if request.method=='GET':
                    obj= RegisterForm()
                    return  render(request,'register.html',{'obj':obj})
                else:
                    obj=RegisterForm(request.POST)
                    if obj.is_valid():
                        print(obj.cleaned_data)
                    else:
                        print(obj.errors)
                    return render(request,'register.html',{'obj':obj})

            <form action="/register/" method="POST" novalidate>
                {% csrf_token %}
                <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>
                <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
                <p>{{ obj.password }}{{ obj.errors.password.0 }}</p>
                <p>{{ obj.phone }}{{ obj.errors.phone.0 }}</p>
                <input type="submit"value="提交">
            </form>            

            
    - Form生成HTML标签
        - GET
            obj = From()
            Form生成HTML标签 <input ‘text’ name='t1' />
        - POST
            obj = Form(request.POST)
            Form生成HTML标签 <input ... value='xx'/>
            
    - Ajax,仅用验证功能
    - Form,验证功能,生成HTML标签    

    
        
    - 常用字段:
        CharField
        ...
        定义正则表达式
    - 字段参数:
        -验证:
            required
            error_message
            
        -生成HTML标签
            widget=widgets.select,  # 生成标签,推荐使用
            
            # 以下不推荐
            label='用户名',         # bj.t1.tabel
            disabled=True,   
            label_suffix=':',
            initial='666',          # 在input中显示默认值
            help_text='.....',      # 提供帮助信息        

    - 小结:
    
        class Foo(Form):
            user = fields.CharField()  # 验证规则,HTML标签插件
            
        obj = Foo(data = request.POST) # 有HTML标签,含有错误信息
        obj = Foo(initial = {})           # 只有HTML标签
        obj.is_valid()
        obj.errors
        obj.cleaned_data        

    a. 多对多
        - ChoiceField(可被替代)
        - MultiplChoiceField
        
    b. 常用插件
        - CheckBox   # 复选框
        - radio
        - input
        - textarea
        - File
        
    c. 插件示例:    
    
        # class TestForm(Form):
        #     t1 = fields.CharField(
        #         widget=widgets.Textarea(attrs={})
        #         widget=widgets.PasswordInput()            # 密码输入框
        #     )
        #     t2 = fields.CharField(
        #         widget=widgets.CheckboxInput               # 单选框
        #     )
        #     t3 =fields.MultipleChoiceField(
        #         choices=[(1,"篮球"),(2,'足球'),(3,'xxx')],
        #         widget=widgets.CheckboxSelectMultiple()    # 多选
        #     )
        #     t4 =fields.ChoiceField(
        #         choices=[(1,"篮球"),(2,'足球'),(3,'xxx')],
        #         widget=widgets.RadioSelect                  # 互斥
        #     )
        #     t5 =fields.FileField(
        #         widget=widgets.FileInput                    # 文件对象
        #     )

        # def test(request):
        #     obj=TestForm(initial={'t3':[2,3]})
        #     return render(request,'test.html',{'obj':obj})

    - Select框:
    
        单选
            cls_id = fields.IntegerField(
                # widget=widgets.Select(choices=[(1,'上海'),(2,'北京')])
                widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'),attrs={'class': 'form-control'})
            )
            
            cls_id = fields.ChoiceField(
                choices=models.Classes.objects.values_list('id','title'),
                widget=widgets.Select(attrs={'class': 'form-control'})
            )
                
            obj = FooForm({'cls_id':1})
            
        多选
            xx = fields.MultipleChoiceField(
                choices=models.Classes.objects.values_list('id','title'),
                widget=widgets.SelectMultiple
            )
            
            obj = FooForm({'cls_id':[1,2,3]})
        
            
    - 修复Bug,刷新无法动态显示数据库内容:
    
        方式一:不推荐
            from django.forms import models as form_model
            class TeacherForm(Form):
                tname = fields.CharField(min_length=2)
                # xx = form_model.ModelMultipleChoiceField(queryset=models.Classes.objects.all())
                # xx = form_model.ModelChoiceField(queryset=models.Classes.objects.all())

        方式二:
            # 单选实现:ChoiceField Select
            cls_id=fields.ChoiceField(
                # widget=widgets.Select(choices=[(1,'上海'),(2,'北京')])
                # widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'),attrs={'class':'form-control'})
                widget=widgets.Select(attrs={'class':'form-control'})
            )
            def __init__(self,*args,**kwargs):
                super(StudentForm,self).__init__(*args,**kwargs)
                self.fields['cls_id'].choices=models.Classes.objects.values_list('id','title')

            # 多选实现:fields.MultipleChoiceField choices
            c2t =fields.MultipleChoiceField(
                # choices=models.Classes.objects.values_list('id','title'),
                widget=widgets.SelectMultiple()
            )
            def __init__(self,*args,**kwargs):
                super(TeacherForm,self).__init__(*args,**kwargs)
                self.fields['c2t'].choices=models.Classes.objects.values_list('id','title')    

    - 拓展

        from django.core.exceptions import ValidationError
        class TestForm(Form):
            user =fields.CharField()
            pwd = fields.CharField()

            def clean_user(self):
                # 验证用户名是否存在
                v = self.cleaned_data['user']
                if models.Student.objects.filter(name=v).count():
                    # raise ValidationError('用户名已经存在',code='')
                    raise ValidationError('用户名已经存在')
                return self.cleaned_data['user']

            def clean_pwd(self):
                return self.cleaned_data['pwd']

            def clean(self):
                # 所有值进行验证
                # hook
                user =self.cleaned_data.get('user')
                email =self.cleaned_data.get('email')
                if models.Student.objects.filter(user=user,email=email).count():
                    raise ValidationError('用户名邮箱联合已经存在')
                return self.cleaned_data

            def _post_clean(self):
                # 自定制功能,一般用不着
                pass    
    
    - is_valid 验证:
    
        - 字段 = 默认正则表达式
             - 额外的正则
                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开头')],
                    )
        - clean_字段,必须返回值
        - clean()  
            有返回值:cleaned_data = 返回值
            无返回值:cleaned_data = 原来的值    
            
    - Form总结:
    
        1. 使用
            class Foo:
                xx = xxxxxx() # 正则,插件
                            
                def clean_xx():
                    ..
                            
                def clean():
                    pass
                    
        2. 页面展示
            obj = Foo()
            obj = Foo(init..)
            
            # 灵活
                <form>
                    {{obj.xx}}
                    {{obj.xx}}
                </form>
            # 简单
                {{obj.as_p}}
                <ul>
                    {{obj.as_ul}}
                </ul>
                <table>
                    {{obj.as_table}}
                </table>

        3. 后台
            is_valid()
            clean_data
            errors        

    - 文件上传
    
        def f1(request):
            if request.method=='GET':
                return render(request,'f1.html')
            else:
                import os
                # request.POST  # 普通文本在此
                file_obj=request.FILES.get('fafafa')
                print(file_obj.name)
                print(file_obj.size)
                f = open(os.path.join('static',file_obj.name),'wb')
                for chunk in file_obj.chunks():
                    f.write(chunk)
                f.close()
                return render(request,'f1.html')
        """
            <form method="POST" action="/f1/" enctype="multipart/form-data">
                {% csrf_token %}
                <input type="text"name="user">
                <input type="file"name="fafafa">
                <input type="submit"value="提交">
            </form>
        """

        class F2Form(Form):
            user =fields.CharField()
            fafafa =fields.FileField()

        def f2(request):
            if request.method=='GET':
                obj = F2Form()
                return render(request,'f2.html',{'obj':obj})
            else:
                obj =F2Form(data=request.POST,files=request.FILES)
                if obj.is_valid():
                    print(obj.cleaned_data.get('fafafa').name)
                    print(obj.cleaned_data.get('fafafa').size)
                return render(request,'f2.html',{'obj':obj})
        """
            <form method="POST" action="/f2/" enctype="multipart/form-data">
                {% csrf_token %}
                {{ obj.user }}
                {{ obj.fafafa }}
                <input type="submit"value="提交">
            </form>
        """           

posted @ 2020-01-18 21:05  badweather  阅读(42)  评论(0编辑  收藏  举报