s14_07_Form_基础

FORM            


- Django的Form主要具有一下几大功能:

    生成HTML标签
    验证用户数据(显示错误信息)
    HTML Form提交保留上次提交数据
    初始化页面显示内容
    
    
- 小试牛刀

1、创建Form类

    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields
    
    class MyForm(Form):
        user = fields.CharField(
            widget=widgets.TextInput(attrs={'id': 'i1', 'class': 'c1'})
        )
    
        gender = fields.ChoiceField(
            choices=((1, '男'), (2, '女'),),
            initial=2,
            widget=widgets.RadioSelect
        )
    
        city = fields.CharField(
            initial=2,
            widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
        )
    
        pwd = fields.CharField(
            widget=widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
        )

2、View函数处理

    from django.shortcuts import render, redirect
    from .forms import MyForm
    
    
    def index(request):
        if request.method == "GET":
            obj = MyForm()
            return render(request, 'index.html', {'form': obj})
        elif request.method == "POST":
            obj = MyForm(request.POST, request.FILES)
            if obj.is_valid():
                values = obj.clean()
                print(values)
            else:
                errors = obj.errors
                print(errors)
            return render(request, 'index.html', {'form': obj})
        else:
            return redirect('http://www.google.com')

3、生成HTML

    <form action="/" method="POST" enctype="multipart/form-data">
        <p>{{ form.user }} {{ form.user.errors }}</p>
        <p>{{ form.gender }} {{ form.gender.errors }}</p>
        <p>{{ form.city }} {{ form.city.errors }}</p>
        <p>{{ form.pwd }} {{ form.pwd.errors }}</p>
        <input type="submit"/>
    </form>
    
    



- 动态select数据


    user_type = fields.ChoiceField(
        # choices=[(1,'普通用户'),(2,'超级用户')],
        # choices=models.UserType.objects.values_list('id','name'),
        # 增加后无法更新,静态字段
        choices=[],
        widget = widgets.Select
    )
    user_type2 = fields.CharField(widget=widgets.Select(choices=[]))


    # 解决方法二
    user_type3 = ModelChoiceField(
        empty_label='请选择用户类型',
        queryset=models.UserType.objects.all(),
        to_field_name='id'
        # 依赖 models.py中的 def __str__(self): return self.name
        # 否则选项的是对象
    )
    # 解决方法一(推荐)
    def __init__(self,*args,**kwargs):
        # 自定义方法,重新获取
        super(UserInfoForm,self).__init__(*args,**kwargs)
        self.fields['user_type'].choices = models.UserType.objects.values_list('id','name')
        self.fields['user_type2'].widget.choices = models.UserType.objects.values_list('id','name')
    
    
- 数据验证(强大)

    验证顺序:
    
        字段:
            正则  ==>  clean_fields  
        整体:
            clean  ==>  _post_clean
        
    源码查找:
    
        is_valid()    errors    full_clean    _clean_fields    clean_fields
                                              _clean_form      clean
                                              _post_clean
    
    整体错误信息:
    
        ‘__all__’  'NON_FIELD_ERRORS'    
        
        
    代码示例:
    
        class LoginForm(forms.Form):
            user =fields.CharField()
            pwd =fields.CharField()
            # 需整体显示错误信息
            def clean_user(self):
                c = models.UserInfo.objects.filter(name=self.cleaned_data['user']).count()
                if not c:
                    return self.cleaned_data['user']
                else:
                    raise ValidationError('用户名已经存在',code='xxx')

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

            def clean(self):
                c = models.UserInfo.objects.filter(name=self.cleaned_data['user'],pwd=self.cleaned_data['pwd']).count()
                if c:
                    return self.clean_data
                else:
                    raise ValidationError('用户名或密码错误')

            def _post_clean(self):
                pass

- 序列化

    关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,
    特别的Ajax请求一般返回的为Json格式。

    1、serializers

        from django.core import serializers
        
        ret = models.BookType.objects.all()
        
        data = serializers.serialize("json", ret)
    2、json.dumps

        import json
        
        #ret = models.BookType.objects.all().values('caption')
        ret = models.BookType.objects.all().values_list('caption')
        
        ret=list(ret)
        
        result = json.dumps(ret)
    3、由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:

        import json
        from datetime import date
        from datetime import datetime
           
        class JsonCustomEncoder(json.JSONEncoder):
            
            def default(self, field):
            
                if isinstance(field, datetime):
                    return o.strftime('%Y-%m-%d %H:%M:%S')
                elif isinstance(field, date):
                    return o.strftime('%Y-%m-%d')
                else:
                    return json.JSONEncoder.default(self, field)
           
           
        # ds = json.dumps(d, cls=JsonCustomEncoder)
    
    示例:

        # djang 默认序列化
        # from django.core import serializers
        # ret = models.UserType.objects.all()
        # data = serializers.serialize("json", ret)
        # return HttpResponse(data)

        # 自定制
        import json
        v = models.UserType.objects.values_list('id','name')
        v=list(v)
        return HttpResponse(json.dumps(v))                

    - ErrorDict
    
        - 自定义encoder
        
    - QuerySet
    
        第一种:
            from django.core import serializers
            
            v = models.tb.objects.all()
            data = serializers.serialize("json", v)
            
        第二种:
            
            如果有时间进行排除处理。
            
            import json
            from datetime import date
            from datetime import datetime
               
            class JsonCustomEncoder(json.JSONEncoder):
                
                def default(self, field):
                
                    if isinstance(field, datetime):
                        return field.strftime('%Y-%m-%d %H:%M:%S')
                    elif isinstance(field, date):
                        return field.strftime('%Y-%m-%d')
                    else:
                        return json.JSONEncoder.default(self, field)

            v = models.tb.objects.values('id','name','ctime')
            v = list(v)
            v = json.dumps(v,cls=JsonCustomEncoder)



        
- FORM 代码
    
    # views.py
    
        from django import forms
        from django.forms import widgets
        from django.forms import fields
        class FM(forms.Form):
            # 字段本身只做验证
            user = fields.CharField(
                error_messages={'required':'用户名不能为空'},
                widget= widgets.Textarea(attrs={'class':'c1'}),
                label='用户名',
                initial='root',
                )
            pwd =fields.CharField(
                max_length=12,
                min_length=6,
                error_messages={'required':'密码不能为空',
                                'min_length':'密码长度不能小于6位',
                                'max_length':'密码长度不能超过12位'},
                widget=widgets.PasswordInput
            )
            email = fields.EmailField(error_messages={'required':'用户名不能为空','invalid':'邮箱格式错误'})

        from app01 import models
        def fm(request):
            if request.method=='GET':
                obj = FM()
                return render(request,'fm.html',{'obj':obj})
            elif request.method =='POST':
                # 获取数据,验证
                # 成功后获取正确数据,失败显示错误信息
                obj =FM(request.POST)
                if obj.is_valid():
                    print(obj.cleaned_data)
                    # models.Userinfo.bojects.create(**cleaned_data)
                else:
                    # print(obj.errors)
                    # print(obj.errors.as_json())
                    # print(obj.errors['user'][0])
                    return render(request,'fm.html',{'obj':obj})
    # html

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
            <form action="/fm/"method="POST">
                {% csrf_token %}
                <p>{{ obj.user.label }}{{ obj.user }}{{ obj.errors.user.0 }}</p>
                <p>{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>
                <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
        {#        {{ obj.as_p }}#}
        {#        {{ obj.as_ul }}#}
        {#        <table>{{ obj.as_table }}</table>#}
                <p><input type="submit"></p>
            </form>
        </body>
        </html>

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