• python django基础一web框架的本质


    web框架的本质就是一个socket服务端,而浏览器就是一个socker客户端,基于请求做出相应,客户端先请求,服务器做出对应响应

    按照http协议的请求发送,服务器按照http协议来相应,这样的通信就可以自己实现web框架了

    简单web框架

    import socket
    
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))  # 把地址绑到套接字
    server.listen()  # 监听链接
    while 1:
        conn, addr = server.accept()  # 接受客户端连接
        from_b_msg = conn.recv(1024).decode('utf-8')  # 接收客户端信息
        print(from_b_msg)
        path = from_b_msg.split('
    ')[0].split()[1]  # 赛选到客户端的第一行信息
    
        conn.send(b'HTTP/1.1 200 ok
    
    ')
        # http响应格式 1.状态行 回车符 换行符  2.相应头部头部字段:值 回车符 换行符 回车符 换行符响应正文
    
        # conn.send(b'hello')
        if path == '/':
            # 只写这一个 你会发现 该 网页css js 应用都没应用上 因为他们 请求/test.css /timg.jpg
            with open('test.html', 'rb') as f:
                data = f.read()
            conn.send(data)
            conn.close()
        elif path == '/test.css':
            with open('test.css', 'rb') as f:
                data = f.read()
            conn.send(data)
            conn.close()
        elif path == '/timg.jpg':
            with open('timg.jpg', 'rb') as f:
                data = f.read()
            conn.send(data)
            conn.close()
        elif path == '/test.js':
            with open('test.js', 'rb') as f:
                data = f.read()
            conn.send(data)
            conn.close()
        elif path == '/meinv.ico':
            with open('meinv.ico', 'rb') as f:
                data = f.read()
            conn.send(data)
            conn.close()

    test.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <title>Bootstrap 101 Template</title>
        <link rel="stylesheet" href="test.css">
        <link rel="icon" href="meinv.ico">
    
        <!-- Bootstrap -->
        <!--<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">-->
    
        <style>
    
        </style>
    </head>
    <body>
    
    
    <h1>来首诗,菩提本无树,明镜亦非台</h1>
    
    <!--<img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1550637152712&di=1caeff14731881d6d2ad4d9681ad031a&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F0b55b319ebc4b7454d716709c5fc1e178b8215c3.jpg" alt="">-->
    <img src="timg.jpg" alt="">
    
    
    <!--<script src="jquery.js"></script>-->
    <!--<script src="bootstrap/js/bootstrap.min.js"></script>-->
    <!--<script>-->
    
        <!--alert('xxx');-->
    
    <!--</script>-->
    <script src="test.js"></script>
    
    </body>
    </html>

    test.css

    h1{
        background-color: green;
    }
    img{
        width: 200px;
        height: 200px;
    }

    test.js

    alert('xxx');
    这2个图片 我就不提供了

    timg.jpg
    meinv.ico

    超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)

    HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。

    工作原理

    1.客户端到连接服务器

    一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接:如http://www.baidu.com

    2.发送http请求

    通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。

    URL包含:/index/index2?a=1&b=2;路径和参数都在这里。

    3.服务接收请求并返回http响应

    Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。

     4.释放连接tcp连接

    若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;

     

    5.客户端浏览器解析HTML内容

    客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

    只加根判断应答会出现 下面情况

    请求方式: get与post请求(通过form表单我们自己写写看)

    • GET提交的数据会放在URL之后,也就是请求行里面,以?分割URL和传输数据,参数之间以&相连,如EditBook?name=test1&id=123456.(请求头里面那个content-type做的这种参数形式,后面讲) POST方法是把提交的数据放在HTTP包的请求体中.
    • GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
    • GET与POST请求在服务端获取请求数据方式不同,就是我们自己在服务端取请求数据的时候的方式不同了,这句废话昂。

    http状态码

    • 1xx消息——请求已被服务器接收,继续处理
    • 2xx成功——请求已成功被服务器接收、理解、并接受
    • 3xx重定向——需要后续操作才能完成这一请求
    • 4xx请求错误——请求含有词法错误或者无法被执行
    • 5xx服务器错误——服务器在处理某个正确请求时发生错误

     

    高级点的 web框架

    from threading import Thread
    import socket
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen()
    
    def html(conn):
        with open('test.html', 'rb') as f:
            data = f.read()
        conn.send(data)
        conn.close()
    
    def js(conn):
        with open('test.js', 'rb') as f:
            data = f.read()
    
        conn.send(data)
        conn.close()
    
    def css(conn):
        with open('test.css', 'rb') as f:
            data = f.read()
    
        conn.send(data)
        conn.close()
    
    def img(conn):
        with open('timg.jpg', 'rb') as f:
            data = f.read()
    
        conn.send(data)
        conn.close()
    
    def ico(conn):
        with open('meinv.ico', 'rb') as f:
            data = f.read()
        conn.send(data)
        conn.close()
    
    
    url = [
        ('/', html),
        ('/test.css', css),
        ('/timg.jpg', img),
        ('/test.js', js),
        ('/meinv.ico', ico),
    ]
    
    while 1:
        conn, addr = server.accept()
        from_b_msg = conn.recv(1024).decode('utf-8')
    
        path = from_b_msg.split('
    ')[0].split(' ')[1]
        conn.send(b'HTTP/1.1 200 ok
    k1:v1
    
    ')
        for i in url:
            if i[0] == path:
                t=Thread(target=i[1],args=(conn,))
                t.start()

    根据不同路径返回不同页面 web框架  返回动态页面web框架

    from threading import Thread
    import socket
    server = socket.socket()
    # server.bind(('192.168.12.45',8080))
    server.bind(('127.0.0.1',8080))
    server.listen()
    
    import datetime
    def base(conn):
        with open('base.html','r',encoding='utf-8') as f:
            data = f.read()
        t1 = datetime.datetime.now()
        new_data = data.replace('@xx@',str(t1))
        conn.send(new_data.encode('utf-8'))
    
    #conn是形参 是发送消息conn 管道
    def index(conn):
        with open('index.html', 'rb') as f:
            data = f.read()
        conn.send(data)
    
    def home(conn):
        with open('home.html', 'rb') as f:
            data = f.read()
        conn.send(data)
    
    def articles(conn):
        with open('art.html', 'rb') as f:
            data = f.read()
        conn.send(data)
    
    urlpatterns=[
        ('/',base),
        ('/index',index),
        ('/home',home),
        ('/articles',articles),
    
    ]
    
    while 1:
        conn, addr = server.accept()
        from_b_msg = conn.recv(1024).decode('utf-8')
        print(from_b_msg)
    
        path = from_b_msg.split('
    ')[0].split(' ')[1]
        # print(path)
        conn.send(b'HTTP/1.1 200 ok
    k1:v1
    
    ')
        # conn.send(b'<h1>hello</h1>')
        for url_func in urlpatterns:
            if url_func[0] == path:
                #多线程函数版
                                            #注意这传参是实参
                t = Thread(target=url_func[1],args=(conn,))
                t.start()
                # 简单函数版
                # url_func[1](conn)

    base.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <title>Bootstrap 101 Template</title>
    
        <!-- Bootstrap -->
        <!--<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">-->
    
    
    </head>
    <body>
    
    <h1 style="color: purple;">欢迎来到王者荣耀页面</h1>
    
    <a href="http://127.0.0.1:8080/index">这是index</a>
    <a href="http://127.0.0.1:8080/home">这是home</a>
    
    
    <h1 style="color: pink;">@xx@</h1>
    <!--<script src="jquery.js"></script>-->
    <!--<script src="bootstrap/js/bootstrap.min.js"></script>-->
    
    </body>
    </html>

    index.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <title>Bootstrap 101 Template</title>
    
        <!-- Bootstrap -->
        <!--<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">-->
    
    </head>
    <body>
    
    <div>这是index页面</div>
    
    <!--<script src="jquery.js"></script>-->
    <!--<script src="bootstrap/js/bootstrap.min.js"></script>-->
    
    </body>
    </html>

    home.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <title>Bootstrap 101 Template</title>
    
        <!-- Bootstrap -->
        <!--<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">-->
    </head>
    <body>
    
    <h1>这是home页面</h1>
    
    <!--<script src="jquery.js"></script>-->
    <!--<script src="bootstrap/js/bootstrap.min.js"></script>-->
    
    </body>
    </html>

     form表单提交

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1:8080" method="">
        用户名:<input type="text" name="username">
        密码:<input type="password" name="password">
        <input type="submit"></input>
    </form>
    </body>
    </html>

    server 得到数据

    GET /?username=zaizai&password=123 HTTP/1.1
    Host: 127.0.0.1:8080
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36

    爬虫模拟user-agent

    import requests
    
    # res = requests.get('https://www.jd.com')
    res = requests.get('https://dig.chouti.com/',headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36',
    
    })
    
    # print(res.text)
    
    with open('ct.html','w',encoding='utf-8') as f:
        f.write(res.text)

    wsgire模块

    from wsgiref.simple_server import make_server
    # wsgiref本身就是个web框架,提供了一些固定的功能(请求和响应信息的封装,不需要我们自己写原生的socket了也不需要咱们自己来完成请求信息的提取了,提取起来很方便)
    #函数名字随便起
    def application(environ, start_response):
        '''
        :param environ: 是全部加工好的请求信息,加工成了一个字典,通过字典取值的方式就能拿到很多你想要拿到的信息
        :param start_response: 帮你封装响应信息的(响应行和响应头),注意下面的参数
        :return:
        '''
        start_response('200 OK', [('Content-Type', 'text/html'),('k1','v1')])
        # print(environ)
        print('>>>>>',environ['PATH_INFO'])  #输入地址127.0.0.1:8000,这个打印的是'/',输入的是127.0.0.1:8000/index,打印结果是'/index'
        return [b'<h1>Hello, web!</h1>']
    
    #和咱们学的socketserver那个模块很像啊
    httpd = make_server('127.0.0.1', 8080, application)
    
    print('Serving HTTP on port 8080...')
    # 开始监听HTTP请求:
    httpd.serve_forever()

    基于wsgire模块 起飞版框架 

    先看一下分析图

    manage.py

    from urls import url_patterns
    from wsgiref.simple_server import make_server
    
    
    # 框架主逻辑代码
    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html'), ('k1', 'v1')])
    
        path = environ['PATH_INFO']  # 所有的请求 取到其中的
        print('path>>>', path)
        data = b'page not found ,404!!!'#没有走404
        for path_func in url_patterns:
            if path == path_func[0]:
                data = path_func[1](environ)
        print(data)
        return [data]
    
    
    httpd = make_server('127.0.0.1', 8080, application)
    
    print('Serving HTTP on port 8080...')
    
    httpd.serve_forever()

    ruls文件

    import views
    
    # 路径与函数的对应关系
    url_patterns = [
        ('/', views.base),
        ('/login',views.login),
        ('/auth',views.auth)
    
    ]

    views文件

    import pymysql
    from urllib.parse import parse_qs
    
    
    # 首页处理函数
    def base(environ):
        with open('templates/base.html', 'rb') as f:
            data = f.read()
        return data
    
    
    def login(environ):
        with open('templates/login.html', 'rb') as f:
            data = f.read()
        return data
    
    
    user = None
    
    
    def auth(environ):
        args = parse_qs(environ['QUERY_STRING'])  # 可把用户请求转化成字典
        username = args['username'][0]
        password = args['password'][0]
        # print('>>>>>',parse_qs(args)) #{'a': ['1'], 'b': ['2']}
        conn = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='123456.com',
            database='auth',
            charset='utf8'
        )
        cursor = conn.cursor()
        sql = 'select * from userinfo where name=%s and password=%s;'
        res = cursor.execute(sql, [username, password])
        if res:
            global user
            user = username
            with open('templates/base.html', 'rb') as f:
                data = f.read()
        else:
            data = '密码错误'.encode('gbk')
        return data

    models文件

    # 通过pymysql来创建表
    
    import pymysql
    
    conn = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123456.com',
        database='auth',
        charset='utf8'
    
    )
    
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    
    sql = """
            # create table userinfo(
            #   id int primary key auto_increment,
            #   name char(20) not null unique,
            #   password char(20) not null
            # 
            # );
    
            insert into userinfo(name,password) values('alex','123'),('alexsb','123');
    
    """
    
    cursor.execute(sql)
    
    conn.commit()
    
    conn.close()

    templates文件夹 下面存放html文件

    base.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>欢迎</h1>
    
    
    </body>
    </html>

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form  action="http://127.0.0.1:8080/auth">
        <label for="username">用户名</label>
        <input type="text" id="username" name="username">
        <label for="password">密码</label>
        <input id="password" type="password" name="password">
        <input type="submit">
    </form>
    
    </body>
    </html>

    MVT和MTV的差别

      将来要说的MVC框架是什么呢:

        M:model.py  就是和数据库打交道用的,创建表等操作

        V:View  视图(视图函数,html文件)

        C:controller  控制器(其实就是我百度云代码里面那个urls文件里面的内容,url(路径)分发与视图函数的逻辑处理)

       Django叫做MTV框架

        M:model.py  就是和数据库打交道用的,创建表等操作(和上面一样)

        T:templates  存放HTML文件的

        V:View 视图函数(逻辑处理)

        其实你会发现MTV比MVC少一个url分发的部分

        所以我们学的django还要学一个叫做url控制器(路径分发)的东西,MTV+url控制器就是我们django要学的内容。  

    模版渲染jinja2

    实现了一个简单的动态页面(字符串替换)

    import socket
    from threading import Thread
    from jinja2 import Template
    import datetime
    
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen()
    
    
    def base(conn):
        # with open('base.html','r',encoding='utf-8') as f:
        #     data = f.read()
        # t1 = datetime.datetime.now()
        # new_data = data.replace('@xx@',str(t1))
        # conn.send(new_data.encode('utf-8'))
        with open('jinja2page.html', 'r', encoding='utf-8') as f:
            data = f.read()
    
        t = Template(data)
    
        new_data = t.render({"name": "于谦", "hobby_list": ["烫头", "泡吧"]})
        # return
        conn.send(new_data.encode('utf-8'))
    
    
    urlpatterns = [
        ('/', base),
    
    ]
    
    while 1:
        conn, addr = server.accept()
        from_b_msg = conn.recv(1024).decode('utf-8')
        path = from_b_msg.split('
    ')[0].split(' ')[1]
        # print(path)
        conn.send(b'HTTP/1.1 200 ok
    k1:v1
    
    ')
        # conn.send(b'<h1>hello</h1>')
        for url_func in urlpatterns:
            if url_func[0] == path:
                # 多线程函数版
                t = Thread(target=url_func[1], args=(conn,))
                t.start()
                # 简单函数版
                # url_func[1](conn)
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>姓名:{{name}}</h1>
    
    <ul>
        {% for hobby in hobby_list %}
        <li>{{hobby}}</li>
        {% endfor%}
    </ul>
    </body>
    </html>

    Django下载安装

    pip3 install django==1.11.9
    
    django-admin startproject mysite   创建了一个名为"mysite"的Django 项目:
    
    python manage.py runserver 127.0.0.1:8080  #此时已经可以启动django项目
    
    django-admin startapp app02 或者使用python manage.py startapp blog   #通过执行manage.py文件来创建应用
    
    python manage.py runserver 8080   #本机就不用写ip地址了 如果连端口都没写,默认是本机的8000端口
    
    http://127.0.0.1:8080/时就可以看到

    pycharm 创建方法

    django 简单使用方法

    目录结构

    mysite 目录结构
        manage.py
        mysqite
            settings.py 项目全局的配置信息
            urls.py 路径和函数对应关系
            wsgi.py socket相关的
        app01
            views.py 视图函数 就是业务逻辑代码
             models.py 数剧库相关
        templates 存放html文件的
         django settings 配置文件里面关于这个文件夹的配置
            'DIRS':[os.path.join(BASE_DIR,'templates')]

    urls改变如下

    from blog import views #引入views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
        url(r'^login/', views.login),
        url(r'^home/', views.home)
    ]

    tempalates 下添加需要的html

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>{{ t }}</h1>
    </body>
    </html>

    login.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <title>Bootstrap 101 Template</title>
    
    
    </head>
    <body>
    
    <form action="http://127.0.0.1:8000/login/" method="get">
        <label for="username">用户名</label><input id="username" type="text" name="username">
        <label for="password">密码</label><input id="password" type="password" name="password">
        <input type="submit">
    </form>
    
    
    </body>
    </html>

    在应用app下 添加需要的应用信息

    from django.shortcuts import render,HttpResponse
    import datetime
    
    # Create your views here.
    
    def index(request):
        newdata = str(datetime.datetime.now())
        return render(request, 'index.html', {'t': newdata})
    def home(request):
        return render(request,'login.html')
    
    def login(request):
    
        #获取用户的请求方法
        method = request.method
        if method == 'GET':
        #     #返回页面
        #     return render(request,'login.html')
        #
        # else:
            #post方法获取数据,都是字符串类型
            # uname = request.POST.get('username')
            #get方法获取数据,都是字符串类型
    
            uname = request.GET.get('username')
            pwd = request.GET.get('password')
            print(uname,pwd) #alex 123
    
            if uname == 'sb' and pwd == '222':
                #返回消息,写字符串就行
                return HttpResponse('登录成功')
    
            else:
                return HttpResponse('验证失败')

     进行登陆验证

     

    失败后 会返回登陆失败   成功后返回成功

    index 是一个动态的jianjia2 相应页面

  • 相关阅读:
    004 Optional
    003 Preconditons
    002 splitter
    003 主键问题
    ReportViewer Win32Exception (0x80004005): 创建窗口句柄时出错
    sqlserver删除所有表、视图、存储过程
    win10文件夹 无法显示当前所有者 管理员都不行
    Cannot resolve collation conflict between "Chinese_Taiwan_Stroke_CI_AS" and "Chinese_PRC_CI_AS" in UNION ALL operator occurring in SELECT statement column 1.
    分析器错误消息: Reference.svcmap:未能加载文件
    跨AppDomain通信
  • 原文地址:https://www.cnblogs.com/zaizai1573/p/10408199.html
Copyright © 2020-2023  润新知