zoukankan      html  css  js  c++  java
  • Django框架导读

    一:Django框架应用

    1:web应用:运行在浏览器上的应用

    2:c/s,b/s架构

      client/server:客户端服务器架构,c++

      browser/server:浏览器服务器架构,java,Python

      底层均是基于socket

    3:Python web框架

      a:socket    b:页面路由    c:模板渲染

      Django    a用到wsgiref    b自己写的    c 自己写的    功能全面

      Flask    a用的第三方    b自己写的    c自己写的    小而轻

      Tornado    a自己写的    b自己写的    c自己写的    支持高并发

    二:原生socket服务

    目录结构:

      part1

        -- index.html
        -- server.py

    基础socket服务:

    import socket
    # 利用socket建立服务器对象
    server = socket.socket()
    # 设置ip和端口
    server.bind(('127.0.0.1', 8001))
    # 设置监听
    server.listen(5)
    print('服务器设置成功')
    print('浏览器访问:http://127.0.0.1:8001')
    while True:
        # 阻塞等待客户端数据
        client, address = server.accept()
        # 接收数据
        data = client.recv(1024)
        print('接收到数据: ', data)
        # 返回数据
        client.send(b'Normal Socket Web')
        # 关闭连接(必须关闭每一次连接)
        client.close()  
    
    # 浏览器错误:发送的响应无效,原因:响应不满足http协议
       
    '''
    # 请求发来的数据
    b'GET / HTTP/1.1
    
    Host: 127.0.0.1:8001
    
    Connection: keep-alive
    
    Upgrade-Insecure-Requests: 1
    
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
    
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    
    Accept-Encoding: gzip, deflate, br
    
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    
    Cookie: csrftoken=szfYLDVuqvRhlveNpNE2rp1GYOcI5x7mRNfvkRWTMRNRwWxXMZWOhL1MqknYJ7jg; sessionid=3pphvmw2icub0bea7nn02u6wev17k4uw
    
    
    '
    '''
    基于socket服务
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>测试请求</title>
    </head>
    <body>
    <div>GET</div>
    <form action="http://127.0.0.1:8801" method="GET">
        <input type="text" name="get_usr">
        <input type="submit" value="get提交">
    </form>
    
    <div>POST</div>
    <form action="http://127.0.0.1:8801" method="POST">
        <input type="text" name="post_usr">
        <input type="submit" value="post提交">
    </form>
    </body>
    </html>
    get提交和post提交

    三:HTTP协议

    1:什么是HTTP协议

    HTTP(HyperText Transport Protocol)是超文本传输协议

      基于TCP/IP洗衣的基础上的应用协议,底层实现仍为socket

      基于请求--响应模式:通信一定是从客户端开始,服务器接收到客户端一定会做出对应响应

      无状态:协议不对任何一次通信状态和任何数据做保存

      无连接:一次连接只完成一次请求--响应,请求--响应完毕后会立即断开连接

    2.HTTP工作原理(事务)

     一次HTTP操作称之为一个事务,工作过程可分为四步:

      1:客户端与服务端建立连接

      2:客户端发生一个HTTP协议指定格式的请求

      3:服务器端接收请求后,响应一个HTTP协议指定格式的响应

      4:客户端将服务器的响应显示展现给用户

    3.请求报文

      请求行:GET|POST(请求方式)  /   (请求路径) HTTP  /    1.1(HTTP协议版本)

         请求头:了解

           请求体: GET请求体放在请求路径后进行拼接    POST会在请求行与请求头结束后,以数据包方式单独发送

    POST / HTTP/1.1
    
    Host: 127.0.0.1:8001
    
    Connection: keep-alive
    
    Upgrade-Insecure-Requests: 1
    
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
    
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    
    Accept-Encoding: gzip, deflate, br
    
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    
    
    
    usr=abc&pwd=123

    4.响应报文

        响应行(一定有):HTTP/1.1(http协议版本)    200(状态码)  OK(状态结束)

        响应头:(了解)

        响应体:具体的数据

    HTTP/1.1 200 OK
    
    Content-type:text/html
    
    
    
    Login Success

    5.状态码

    1打头:消息通知

    2打头:请求成功

    3打头:重定向

    4打头:客户端错误(404)

    5打头:服务器端错误

    四:练习代码:

    part2:目录

    import socket
    
    PORT = 8802
    
    def index():
        return b'home page'
        pass
    
    def login():
        with open('login.html', 'rb') as f:
            login_data = f.read()
        return login_data
    
    def ico():
        with open('keji.jpg', 'rb') as f:
            ico_data = f.read()
        return ico_data
    
    method_dic = {
        '/': index,
        '/index': index,
        '/login': login,
        '/favicon.ico': ico,
    }
    
    server = socket.socket()
    server.bind(('127.0.0.1', PORT))
    server.listen(5)
    print("服务端启动:http://127.0.0.1:%s" % PORT)
    
    # 1.浏览器采用http协议方式发生请求
    while True:
        browser, _ = server.accept()
        req_data = browser.recv(1024).decode('utf-8')
        # print(req_data)
        browser.send(b'HTTP/1.1 200 OK
    ')
        browser.send(b'Content-type:text/html
    ')
        browser.send(b'
    ')
    
        # 请求路径有多种多样 => 具体请求路径应该交给具体的功能处理完成对应的响应
        path = req_data.split('
    ')[0].split(" ")[1]
        print(path)
        # print()
        resp_data = b'<h1 style="text-align: center">404</h1>'
        if path in method_dic:
            resp_data = method_dic[path]()
    
        browser.send(resp_data)
        browser.close()
    server
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>登录页面</title>
    </head>
    <body>
    <form action="">
        <input type="text" name="usr">
        <input type="password" name="pwd">
        <input type="submit" value="登录">
    </form>
    </body>
    </html>
    HTML

    可以根据请求HTTP协议数据,解析出请求路径,根据具体路径完成业务逻辑方法,完成对应的响应。

      1:业务逻辑会不断增加,所以业务逻辑要分层单独处理

      2:路径与业务处理方法对应关系也会越来越多,越来越复杂,也可以分离单独处理

      3:自定义服务器功能不健全,稳定性差,可以选择第三方

     改善part2写的part3:

    目录:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>测试请求</title>
    </head>
    <body>
    <div>GET</div>
    <form action="http://127.0.0.1:8803" method="GET">
        <input type="text" name="get_usr">
        <input type="submit" value="get提交">
    </form>
    
    <div>POST</div>
    <form action="http://127.0.0.1:8803" method="POST">
        <input type="text" name="post_usr">
        <input type="submit" value="post提交">
    </form>
    </body>
    </html>
    requestTest
    # 使用遵循了WSGI协议的第三方server
    
    from wsgiref import simple_server
    from day62.教案.part3.urls import urls
    PORT = 8803
    
    
    def send_request(url):
        resp_data = b'404'
        if url in urls:
            resp_data = urls[url]()
        return resp_data
    
    
    def app(environ, response):
        # 请求的数据被解析在environ字典中
        print(environ)  # 请求方式REQUEST_METHOD  请求路径PATH_INFO
        path = environ['PATH_INFO']
        print(path)
    
        # 数据的获取
        # GET 在environ的QUERY_STRING字段中,eg:usr=abc&pwd=123
    
        # POST 数据长度CONTENT_LENGTH  数据存放的io流 wsgi.input eg: usr=abc&pwd=123
        # length = int(environ['CONTENT_LENGTH'])
        # res = environ['wsgi.input'].read(length)
        # print(res)
    
        # 将数据转换成字典
    
    
        resp_data = send_request(path)
        # 用response来规定http响应结果
        # print(response)
        response("200 OK", [('Content-type', 'text/html')])
    
        # 返回的是装有二进制数据的数组
        return [resp_data]
    
    
    if __name__ == '__main__':
        server = simple_server.make_server('127.0.0.1', PORT, app)
        print("服务启动:http://127.0.0.1:%s" % PORT)
        # 保持server运行
        server.serve_forever()
    
    
    # 利用第三方wsgiref服务器完成请求-响应
    server
    from part3.views import *
    
    urls = {
        '/': index,
        '/index': index,
        '/favicon.ico': ico,
        '/login': login,
    }
    urls
    # 结果要返回二进制数据
    
    def ico():
        with open('keji.jpg', 'rb') as f:
            ico_data = f.read()
        return ico_data
    
    
    def index():
        return b'home page'
        pass
    
    
    def login():
        with open('login.html', 'rb') as f:
            login_data = f.read()
        return login_data
    views

    五:jinjia2

    Jinjia2是基于Python下一个被广泛应用的模板引擎,来源于Django的模板引擎,并扩展了其语法和一系列强大的功能,最显著的是增加了沙箱执行功能和可选的自动转义功能,者对于大多数的安全性来说是非常重要的。(基于Unicode并能在Python2.4之后的版本运行,包括Python3)

       有Jinjia改的part4:

    目录:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>login result</title>
    </head>
    <body>
        <!--my login page => %%res%%-->
        my login page => {{ result }}
        <hr>
        {{my_dic}}
        <hr>
    
        {% for k in my_dic %}
        <div>{{k}} : {{my_dic[k]}}</div>
        {% endfor %}
    </body>
    </html>
    login
    from wsgiref import simple_server
    from part4.urls import urls
    
    
    PORT = 8804
    
    
    # 浏览器通过:http://127.0.0.1:8804/login?usr=abc&pwd=123  来模拟get方式登录
    
    def app(environ, response):
        print(environ)
        response("200 OK", [('Content-type', 'text/html')])
        url = environ['PATH_INFO']
    
        res_dic = {}
        if environ.get('REQUEST_METHOD', None) == "GET" and url == "/login":
            res_str = environ['QUERY_STRING']  # usr=abc&pwd=123
            if res_str:  # 如果没有请求提交的数据,就不需要解析数据
                res_list = res_str.split('&') # ['usr=abc', 'pwd=123']
                for k_v_m in res_list:  # k_v_m: 'usr=abc' | 'pwd=123'
                    k_v_l = k_v_m.split('=')  # ['usr', 'abc']  |  ['pwd', '123']
                    res_dic[k_v_l[0]] = k_v_l[1]
    
    
        resp_data = b'404'
        if url in urls:
            resp_data = urls[url](res_dic)
    
        return [resp_data]
    
    
    
    
    
    if __name__ == '__main__':
        server = simple_server.make_server('127.0.0.1', PORT, app)
        print("服务启动:http://127.0.0.1:%s" % PORT)
        # 保持server运行
        server.serve_forever()
    server
    from day62.教案.part4.views import *
    
    urls = {
        '/': index,
        '/index': index,
        '/favicon.ico': ico,
        '/login': login,
    }
    urls
    # 结果要返回二进制数据
    import pymysql
    from jinja2 import Template
    
    def ico(dic=None):
        with open('keji.jpg', 'rb') as f:
            ico_data = f.read()
        return ico_data
    
    
    def index(dic=None):
        return b'home page'
        pass
    
    
    def login(dic=None):
        print(dic)
        usr = dic['usr']
        pwd = dic['pwd']
        # 和数据库进行交互
        conn = pymysql.connect(
            host='127.0.0.1',
            db='dg1',
            user='root',
            passwd='root'
        )
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        row = cursor.execute('select * from user where usr=%s and pwd = %s', [usr, pwd])
    
        # 根据结果渲染动态页面 => 利用第三方jinja2
        # with open('login.html', 'rt') as f:
        #     msg = f.read()
        #
        # if row:
        #     res = 'login success'
        # else:
        #     res = 'login failed'
        #
        # msg = msg.replace("%%res%%", res)
    
        # 模板渲染框架定义了很多模板语法,采用这些语法可以复用html代码
        with open('login.html', 'rt') as f:
            msg = f.read()
        tem = Template(msg)
    
        if row:
            res = 'login success'
        else:
            res = 'login failed'
        msg = tem.render(result=res, my_dic=dic)
    
    
    
        return msg.encode('utf-8')
    views
  • 相关阅读:
    使用PowerDesigner对NAME和COMMENT互相转换
    HIMSS EMRAM新版标准将于2018年1月1日生效
    [转]Scrapy简单入门及实例讲解
    转:Oracle 执行计划(Explain Plan) 说明
    mac 安全控制 允许安装任何来源的包
    [转]Python中出错:ImportError: No module named win32com.client
    Windows环境下安装配置Mosquitto服务及入门操作介绍
    Mosquitto--webServer应用测试结果
    Paho -物联网 MQTT C Cient的实现和详解
    mosquitto设置用户名和密码
  • 原文地址:https://www.cnblogs.com/liuxiaolu/p/10431725.html
Copyright © 2011-2022 走看看