zoukankan      html  css  js  c++  java
  • day78——基础知识复习2

    一、后续课程安排

    1 drf框架
    2 git
    3 redis使用
    4 路飞项目(celery异步)
    5 爬虫(mongodb)
    6 linux
    7 cmdb项目(资产收集)
    8 代码发布系统
    9 flask框架(给你一到两个项目)
    10 数据结构和算法
    11 docker,dockercompose(用docker部署项目,nginx负载均衡,横向扩展),k8s(看情况)
    12 就业辅导(redis高级,Elasticsearch,如何提高项目并发量,分布式锁,分布式id,远程连接docker开发,git冲突如何解决)
    

    二、作业讲解

    作业一:

    前后端传数据三种编码格式,传json格式,原生django不能从POST中取出字典,用中间件或者装饰器前端不管传json还是其他格式,requests对象中有个data属性

    form django.utils.deprecaton import MiddlewareMixin
    
    import json 
    class JsonMiddel(MiddlewareMixin)
    	def process_request(self,request):
            try:
                request.data = json.loads(request.body)
            except Exception as e:
                request.data = request.POST
                            
    

    前端用ajax提交数据:

    <body>
    <form method="post">
        用户名:<input type="text" name="name" id="name">
        密码:<input type="text" name="pwd" id="pwd">
        <input type="submit" value="提交1">
        <input type="button" value="提交" id="submit">
    
    </form>
    
    </body>
    <script>
        $('#submit').click(function () {
            $.ajax({
                url:'/index/',
                type:'post',
                contentType:'application/json',
                data:JSON.stringify({'name':$('#name').val(),'pwd':$('#pwd').val()}),
                //data:{'name':$('#name').val(),'pwd':$('#pwd').val()},
                success:function (data) {
                    console.log(data)
    
                }
            })
    
        })
    </script>
    

    易错点:

    1. form表单和ajax重复提交请求:

      form表单中input的submit类型和button按钮都会触发提交数据的动作,如果有ajax的话,点一次按钮就会提交两次,如果只需要用ajax提交数据那么就绑定input的button类型,或者将button按钮放在form表单外进行绑定。

    2. form django.http.request import QueryDict

      本质是一个字典,但是比字典的功能强大,并且不能修改值,一改就会报错,只能用copy复制一份进行修改。

    ps:CommonMiddleware中间件控制了是否重定向到带/的地址

    """
    当在浏览器中输入的url没有以/结尾,请求到django中间件中会自动拼接上/,然后在匹配一次路由
    这是django的CommonMiddleware帮我们实现的"""
    
    # django.middleware.common.CommonMiddleware 中间件源码
    class CommonMiddleware(MiddlewareMixin):
        ...
        def should_redirect_with_slash(self, request):
            """
            Return True if settings.APPEND_SLASH is True and appending a slash to
            the request path turns an invalid path into a valid one.
            """
            if settings.APPEND_SLASH and not request.path_info.endswith('/'):
                urlconf = getattr(request, 'urlconf', None)
                return (
                    not is_valid_path(request.path_info, urlconf) and
                    is_valid_path('%s/' % request.path_info, urlconf)
                )
            return False
    

    三、python 中的魔法方法(双下滑方法)

    常用的魔法方法:

    • __init__:类实例化对象会触发

    • __stry__:打印对象会触发

    • __call__:对象加()调用会触发,类也是对象,元类(),类的实例化过程调用元类的__call__

    • __new__:在类实例化会触发,它比 __init__早,(造一个空的对象)

    • __del__:del对象或者在对象被回收的时候触发

    • __setattr__/__getattr__:(.拦截方法),当对象.属性的时——》赋值的时候调用__setattr__

      取值的时候调用__getattr__

    • __getitem__/__setitem__:([]拦截),字典添加键值对或者[]取值的时候会触发

    • __enter__/__exit__:上下文管理器,进入with管理的时候触发、with代码块运行结束后触发

    3.1 setattr、getattr、settiem、getitem演示

    # 1 __setattr__与__getattr__
    class MyClass:
        def __init__(self, name):
            self.name = name
    
        def __setattr__(self, name, value):
            if type(value) != str:
                print('名字必须是字符串')
            else:
                # setattr(self,key,value) 内部还是用.赋值,又会触发__setattr__,形成递归报错。
                self.__dict__[name] = value # 不要加引号
    
    
    obj1 = MyClass('zts')
    obj1.name = 123
    print(obj1.name)
    
    
    # 2 __getitem__与__setitem__
    
    class MyClass1:
        def __init__(self, name):
            self.name = name
    
        def __setitem__(self,key,value):
            setattr(self,key,value)
    
        def __getitem__(self, key):
            return getattr(self,key)
    
    
    obj2 = MyClass1('tom')
    obj2['age'] = 18
    print(obj2['age'])
    

    3.1 with上下文管理器

    class Person:
        def __enter__(self):
        	print('我在with管理的时候,会触发')
            return 'xx'  # 进入with语句块执行此方法,此方法如果有返回值就会赋值给as声明的变量
        
        def __exit__(self, exc_type,exc_val,exc_tb):
            print('在退出with代码块,也就是with代码块运行完后会执行此方法')
            print('1',exc_type)
            print('2',exc_val)
            print('3',exc_tb)
            
          
    with Person() as p:  # 这句代码执行,会触发类的__enter__方法
        print(p)  # 打印之后with代码块运行结束,会触发类的__exit__方法
        
    

    四、cookie/session/token

    HTTP协议四大特性:

    1. 无状态
    2. 无连接
    3. 基于请求相应
    4. 基于tcp/ip,应用层协议
    • mysql:c/s架构,底层基于socket,自己封装的协议,mysql的服务端:navicate(c++图形化界面,实现了请求和相应协议)/pymsql(用python语言实现了请求和响应协议)
    • redis:c/s架构,底层基于socket,自己封装的协议
    • docker:c/s架构,基于http协议,使用restfull规范

    是存在浏览器上的键值对,向服务端发送请求,携带它过去(不安全)

    session:

    存在与服务端的键值对,可以放在文件中或者数据库中(mysql/rediex)

    django中session的底层原理:

    # 在中间件中,请求走的时候,process_response,取出request.session的modify属性,判断是否是true,如果是true,表示在视图函数中修改过session,数据库同步修改,如果是false,就不修改,返回给前端sessionid:随机字符串
    # 请求来了,通过sessionid,取出随机字符串--》去数据库中查--》把表的数据转成字典,赋值给request.session,后面视图函数中就可以操作它了
    

    缺点:如果用户量大,存储需要耗费服务端资源

    token:

    token现在应用非常广泛,契合了前后端分离

    JWT:json web token

    五、异常处理

    try:
        print("xxx")
        # print(1/0)
    except Exception as e:
        print(e)
    else:  # 基本上不会用到
        print("正常执行,没有出异常,会走")
    finally:
        print("我是finally")   # 用于会走,无论是否有异常
    

    六、pymsql的使用

    # 1 连接数据库
    conn = pymsql.connect(host='127.0.0.1',
                          user='root',
                          passwrod='1111',
                          database='test',
                          port=3306)
    # 2 获取游标
    cursor = conn.cursor(cursor = pymysql.cursors.DictCursor) # 字典格式
    # 查
    sql_1  = 'select id,name from book'
    cursor.execute(sql_1)
    ret = cursor.fetchall()
    print(ret)
    
    # 插入数据
    sql_2 = 'insert into book(id,name) values(%s,%s)'
    cursor.execute(slq_2,[3,'tom'])
    conn.commit()  # 提交到数据库
    
    # 删除
    sql_3 = 'delete from book where name=%s'
    cursor.execute(sql,['tom'])
    conn.commit()
    
    # 更新
    sql_4 = 'update book set name=%s where id=%s'
    cursor.execute(sql_4,['xxx',1])
    conn.commit()
    
    

    作业:

    1 写一个类,有个name属性,如果name赋值为非字符串,就不让放

    class MyClass:
        def __init__(self, name):
            self.name = name
    
        def __setattr__(self, name, value):
            if type(value) != str:
                print('名字必须是字符串')
            else:
                self.__dict__[name] = value
    
    
    obj1 = MyClass('zts')
    obj1.name = 123
    print(obj1.name)
    obj1.name = 'tom'
    
    """
    名字必须是字符串
    zts
    tom"""
    

    2 通过上下文管理器写一个mysql的连接,通过with管理

    class MySQL:
        conn = None
        cursor = None
    
        def __init__(self, host, port, user, password, database):
            self.host = host
            self.port = port
            self.user = user
            self.password = password
            self.database = database
    
        def __enter__(self):
            import pymysql
            self.conn = pymysql.connect(host=self.host,
                                        port=self.port,
                                        user=self.user,
                                        database=self.database,
                                        password=self.password)
            self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)  # 将查询出来的数据由元祖的形式改成字典
            return self.conn
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.conn.close()
    
    
    with MySQL('127.0.0.1', 3306, 'root', '123123', 'db_py') as conn:
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 1 查
    sql_1 = 'select name,age from student'
    cursor.execute(sql_1)
    ret = cursor.fetchall()
    print(ret)
    
    # 2 增
    sql_2 = 'insert into student(name,age) values(%s,%s)'
    cursor.execute(sql_2, ['tank', 20])
    conn.commit()
    
    # 3 删
    sql_3 = 'delete from student where name=%s'
    cursor.execute(sql_3, ['tom'])
    conn.commit()
    
    # 4 改
    sql_4 = 'update student set name=%s where id>0'
    cursor.execute(sql_4, ['xxx'])
    conn.commit()
    

    3 使用django实现token功能

    # 1 视图函数
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            user_obj = auth.authenticate(request,username=username,password=password)
            if user_obj:
                request.user_id = username
                return HttpResponse('登陆成功')
            else:
                request.user_id = None
                return HttpResponse('登陆失败')
        return render(request,'login.html')
    
    
    # 2 自定义中间件
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    import hashlib
    
    
    class MyMiddleware(MiddlewareMixin):
        def process_request(self, request):
            res = request.COOKIES.get('token')
            if res:
                user_id, user_hash = res.split('|')
                m = hashlib.md5()
                m.update(user_id.encode())
                m.update('世界那么大我想去看看'.encode('utf-8'))
                user_hash_1 = str(m.hexdigest())
                if user_hash_1 == user_hash:
                    print(f'token校验成功,这是{user_id}的信息')
                else:
                    obj = HttpResponse(f'token已被修改,校验失败,无法获取{user_id}的信息')
                    obj.delete_cookie('token')
                    return obj
            else:
                print('没有登陆,无法获取用户信息')
    
        def process_response(self, request, response):
            try:
                user_id = request.user_id
                if user_id:
                    m = hashlib.md5()
                    m.update(user_id.encode())
                    m.update('世界那么大我想去看看'.encode('utf-8'))
                    user_hash = str(m.hexdigest())
                    token_list = [user_id, user_hash]
                    token = '|'.join(token_list)
                    obj = HttpResponse('token设置成功')
                    obj.set_cookie('token', token)
                    return obj
            except Exception:
                return response
    
    
  • 相关阅读:
    【2020Python修炼记】网络编程(三)socket编程之粘包
    2020python作业——scoket编程(一)
    月考二
    【2020Python修炼记】网络编程(二)socket编程之socket 的介绍+TCP/UDP
    Gym100889L
    poj3233
    upper_bound
    lower_bound
    Gym-102141E
    P1020 导弹拦截
  • 原文地址:https://www.cnblogs.com/cainiaoqianxun/p/13227254.html
Copyright © 2011-2022 走看看