• python自动化开发-[第二十天]-form表单,CBV和FBV,序列化


    1、CBV和FBV的用法

    2、序列化用法

    3、form表单

    一、CBV和FBV

      1、cbv是 class based view(基于类),fbv是function based view(基于函数)

      2、cbv基于dispatch进行反射,get获取,post提交

      3、应用场景:登录认证(继承dispatch,在dispatch里做session验证)

       CBV第一种方式继承

      1、单继承

         扫盲:(继承的时候,一定要清楚self是哪个类实例化出来的对象,下例,self为B实例化的对象,任何属性优先从自己里面找,找不到在去父类里找)

    class A(object):
        def aaa(self):
            print('from A')
        def bbb(self):
            self.aaa()
    
    class B(A):
        def aaa(self):
            print('from B')
    
    c = B()
    c.aaa()
    

      

    from django.views import View
    class BaseView(View):
        def dispatch(self, request, *args, **kwargs):  # 继承父类的dispatch,因为父类里有返回值,所以也要有return
            if request.session.get('username'):
                response = super(BaseView, self).dispatch(request, *args, **kwargs)
                return response
            else:
                return redirect('/login.html')
    
    class IndexView(BaseView):
    
        def get(self, request, *args, **kwargs):
            return HttpResponse(request.session['username'])
    

      2、多继承(继承顺序从左到右)

    class BaseView(object):
        def dispatch(self, request, *args, **kwargs):
            if request.session.get('username'):
                response = super(BaseView,self).dispatch(request, *args, **kwargs)
                return response
            else:
                return redirect('/login.html')
    
    class IndexView(BaseView,View):#先去找BaseView,BaseView中未定义在去找View
    
        def get(self,request,*args,**kwargs):
            return HttpResponse(request.session['username'])
    

      CBV第二种方式装饰器

    from django.utils.decorators import method_decorator
    
    def auth(func): #定义装饰器
        def inner(request,*args,**kwargs):
            if request.session.get('username'):
                obj = func(request,*args,**kwargs)
                return obj
            else:
                return redirect('/login.html')
        return inner
    
    @method_decorator(auth,name='get')  #放在类顶部就需要method_decorator这个装饰器
    class IndexView(View):
    
        @method_decorator(auth) #放在dispatch上就相当于全局都需要经过认证
        def dispatch(self, request, *args, **kwargs):
            if request.session.get('username'):
                response = super(IndexView,self).dispatch(request, *args, **kwargs)
                return response
            else:
                return redirect('/login.html')
    
        @method_decorator(auth)
        def get(self,request,*args,**kwargs):
            return HttpResponse(request.session['username'])
    
        @method_decorator(csrf_exempt)  # 无效 csrf 放到post函数上的装饰器,是无效的,需要放到dispath上或者类上
        def post(self,request,*args,**kwargs):
            return HttpResponse(request.session['username'])
    

      特殊csrf

    特殊:CSRF
    	class IndexView(View):
    	
    		@method_decorator(csrf_exempt) #不能放属性上,只能放在全局
    		def dispatch(self, request, *args, **kwargs):
    			return super(LoginView,self).dispatch(request, *args, **kwargs)
    
    
    		def get(self,request,*args,**kwargs):
    			return HttpResponse(request.session['username'])
    			
    		
    		def post(self,request,*args,**kwargs):
    			return HttpResponse(request.session['username'])
    

     二、序列化

      方式一 serialize,可以序列化对象

    user_list = models.UserInfo.objects.all()
    data = serializers.serialize("json", user_list)
    [
    	{"model": "app01.userinfo", "pk": 1, "fields": {"username": "u5174u666e", "password": "123123"}}, 
    	{"model": "app01.userinfo", "pk": 2, "fields": {"username": "u94f6u79cbu826f", "password": "666"}}
    ]
    

      方式二 json dumps(只能序列化python支持的数据类型)

    user_list = models.UserInfo.objects.values('id','username')
    user_list = list(user_list)
    data = json.dumps(user_list)
    [
    	{"username": "u5174u666e", "id": 1}, 
    	{"username": "u94f6u79cbu826f", "id": 2}
    ]
    

      json dumps不能序列化时间,通过自定义来支持序列化时间

    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)
    
    
    user_list = [
    	{'id':1,'name':'alex','ctime': datetime.now()},
    	{'id':2,'name':'eric','ctime': datetime.now()}
    ]
    
    data = json.dumps(user_list,cls=JsonCustomEncoder)
    print(data)
    
    
    '''
    [{"ctime": "2017-09-15 06:47:53", "id": 1, "name": "alex"}, {"ctime": "2017-09-15 06:47:53", "id": 2, "name": "eric"}]
    
    '''
    

     三、Form表单验证

      1、form表单的功能

          表单验证和生成表单

      示例:用户管理
        a. 添加用户页面
          - 显示HTML标签
          - 提交:数据验证
          - 成功之后保存
          - 错误显示错误信息

      创建Form类(本质就是正则表达式的集合) 

    from django.forms import Form
    from django.forms import fields
    from django.forms import widgets
    
    class UserForm(Form):
    	username = fields.CharField(
    		required=True, #默认就为true,可以不填
    		error_messages={'required':'用户名不能为空'}, #自定义错误信息
    		widget=widgets.TextInput(attrs={'class':'form-control'}) #额外自定义样式
    	)
    	password = fields.CharField(
    		required=True,
    		error_messages={'required': '邮箱不能为空','invalid':'邮箱格式错误'}, #邮箱的错误提示需要写在invalid里
    		widget = widgets.TextInput(attrs={'class': 'form-control'})
    	)
    	# fields.EmailField()
    	# fields.GenericIPAddressField(protocol='ipv4')
    
    	ut_id = fields.ChoiceField( #单选和多选会有个下拉框内容填充的问题,默认类的属性只加载一次,需要通过构造方法,使得每次调用都更新一次
    		choices=[],
    		widget=widgets.Select(attrs={'class':'form-control'})
    	)
    
    	role_id = fields.MultipleChoiceField(
    		choices=[],
    		widget=widgets.SelectMultiple(attrs={'class':'form-control'})
    	)
    
    	def __init__(self,*args,**kwargs):
    		super(UserForm,self).__init__(*args,**kwargs)
    		# self.fields已经有所有拷贝的字段
    		self.fields['ut_id'].choices = models.UserType.objects.values_list('id','title')
    		self.fields['role_id'].choices = models.Role.objects.values_list('id','caption')
    

     例子添加用户:

    view里 

    from django.forms import Form,fields,widgets
    class UserForm(Form):
        '''用户表单'''
        username = fields.CharField(required=True,error_messages={'required':'用户名不能为空'})
    
        password = fields.CharField(required=True,error_messages={'required':'密码不能为空'})
    
        # ip = fields.GenericIPAddressField(required=True,error_messages={'required':'IP不能为空','invalid':'IP格式错误'})
    
        ut_id = fields.ChoiceField(choices=[])
        def __init__(self,*args,**kwargs):
            super(UserForm,self).__init__(*args,**kwargs)
            self.fields['ut_id'].choices = models.UserType.objects.values_list('id','title')
    
    class AddUserView(AuthView,View):
        '''添加视图'''
    
        def get(self,request,*args,**kwargs):
            form = UserForm()
            return render(request,'add_user.html',{'form':form})
    
        def post(self,request,*args,**kwargs):
            form = UserForm(request.POST) 
            if form.is_valid():
                print(form.cleaned_data)
                models.UserInfo.objects.create(**form.cleaned_data)
                return redirect('/users.html')
            else:
                print(form.errors)
                return render(request,'add_user.html',{"form":form})
    

     tempelate:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>添加用户</h1>
        <form method="POST" novalidate>
            {% csrf_token %}
            <p>
                用户名: {{ form.username }} {{ form.errors.username.0 }}
            </p>
            <p>
                密码: {{ form.password }}  {{ form.errors.password.0 }}
            </p>
    {#        <p>#}
    {#            ip: {{ form.ip }}  {{ form.errors.ip.0 }}#}
    {#        </p>#}
            <p>
                用户类型: {{ form.ut_id }} {{ form.errors.ut_id.0 }}
            </p>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    

       知识点:form(request.POST),将request内的数据传递给from表单,form表单会进行正则验证,通过obj.is_valid(), 如果正常, 返回值就是obj.cleaned_data,如果出现异常,异常信息会以字典形式存放在obj.errors 。一个输入框多条错误信息 一般只取第一条错误信息,处理完这一条在去处理其他

    带默认值的添加标签:

      

    class EditUserView(AuthView,View):
        def get(self,request,pk):
            obj = models.UserInfo.objects.filter(id=pk).first()
            role_id_list = obj.rl.values_list('id')
            v = list(zip(*role_id_list))[0] if role_id_list else []
            form = UserForm(initial={'username': obj.username, 'password': obj.password, 'ut_id': obj.ut_id,'role_id':v})
            return render(request,'edit_user.html',{'form':form})
    
        def post(self,request,pk):
            form = UserForm(data=request.POST)
            if form.is_valid():
                # # {'username': 'xxxxx', 'password': 'xxxxx', 'ut_id': '1',role_id:}
                role_id = form.cleaned_data.pop('role_id')
                # 用户表更新
                query = models.UserInfo.objects.filter(id=pk)
                query.update(**form.cleaned_data)
                obj = query.first()
                obj.rl.set(role_id)
    
                return redirect('/users.html')
            else:
                print(form.errors)
                return render(request, 'edit_user.html', {'form': form})
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>编辑用户</h1>
        <form method="POST" novalidate>
            {% csrf_token %}
            <p>
                用户名: {{ form.username }} {{ form.errors.username.0 }}
            </p>
            <p>
                密码: {{ form.password }}  {{ form.errors.password.0 }}
            </p>
    {#        <p>#}
    {#            ip: {{ form.ip }}  {{ form.errors.ip.0 }}#}
    {#        </p>#}
            <p>
                用户类型: {{ form.ut_id }} {{ form.errors.ut_id.0 }}
            </p>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    

    通过ajax+form表单验证,实现注册功能

      view:

    class RegisterForm(Form):
        user = fields.CharField(required=True,min_length=6,max_length=18)
        email = fields.EmailField(required=True,min_length=6,max_length=18)
        password = fields.CharField(min_length=12)
    import json
    
    def register(request):
        if request.method == 'GET':
            form = RegisterForm()
            return render(request,'register.html',{'form':form})
        else:
            response = {'status': True,'data': None,'msg':None}
            form = RegisterForm(request.POST)
            if form.is_valid():
                print(form.cleaned_data)
                # 数据库中添加一条数据
                # return redirect('/login.html') # ajax跳转,错错错
            else:
                response['status'] = False
                response['msg'] = form.errors
            return HttpResponse(json.dumps(response))
    

     tempelate

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form id="f1">
            {% csrf_token %}
            <p>用户名:{{ form.user }}</p>
            <p>密码:{{ form.password }}</p>
            <p>邮箱:{{ form.email }}</p>
            <input type="button" value="提交" onclick="submitForm();" />
        </form>
        <script src="/static/jquery-3.2.1.js"></script>
        <script>
            function submitForm() {
                $('#f1 .error').remove();
    
                $.ajax({
                    url: '/register.html',
                    type: 'POST',
                    data: $('#f1').serialize(),
                    dataType: 'JSON',
                    success:function (arg) {
                        if(arg.status){
                            location.href = "/login.html";
                        }else{
                            /*
                            arg.msg = {
                                email: ['xxxxx',]
                                password: ['xxxxx',]
                                user: ['xxxxx',]
                            }
                             */
                            $.each(arg.msg,function (k,v) {
                                var tag = document.createElement('span');
                                tag.innerHTML = v[0];
                                tag.className = "error";
                                // <span class='error'>v[0]</span>
                                $('#f1 input[name="'+k+'"]').after(tag);
                            })
                        }
                    }
                })
            }
        </script>
    
    </body>
    </html>
  • 相关阅读:
    第06课:GDB 常用命令详解(下)
    第05课:GDB常用命令详解(中)
    第04课:GDB常用命令详解(上)
    第03课:GDB常用的调试命令概览
    第02课:启动GDB调试
    第01课:调试信息与调试原理
    数据库(二)
    数据库笔记(一)
    acedSSGet 翻译
    ObjectARX动态添加AutoCAD传统下拉菜单入门篇(一)
  • 原文地址:https://www.cnblogs.com/liujiliang/p/7513102.html
Copyright © 2020-2023  润新知