• Django 系列博客(一)


    Django 系列博客(一)

    前言

    学习了 python 这么久,终于到了Django 框架。这可以说是 python 名气最大的web 框架了,那么从今天开始会开始从 Django框架的安装到使用一步步的学习,这系列博客不会像前端的那样水了(立个 flag),希望可以成为高质量的博客。那么本篇博客介绍 Django 的安装以及如何在电脑上运行第一个 Django 应用。

    Django 的安装

    Django 的安装很简单,在 win 和 mac 上面都可以使用 pip 安装命令安装,也可以通过 pycharm 安装,或者下载文件在命令行使用安装工具安装。

    接下来我在 ubuntu 上安装做示例。

    在这里还安装了一个依赖包 pytz。这是用来做时区转换的一个第三方库。

    其他平台的 pip 安装方式一样,不过要选用 python3的对应 pip 来安装,因为现在的 Django 版本已经不支持 python2了。

    虚拟环境的安装

    什么是虚拟环境

    • 对真实的 python 解释器的一个拷贝版本
    • 事实有效,可以独立存在并运行解释 python 代码
    • 可以在计算机上拷贝多个虚拟环境

    为什么要使用虚拟环境

    • 保证真实环境的纯净性
    • 框架的多版本共存
    • 方便做框架的版本迭代
    • 降低多框架共存的维护成本

    安装虚拟环境

    1. 通过 pip 安装虚拟环境库

    因为我之前已经下载好了,所以这里直接显示请求已经完成,并且后面是安装的绝对路径。

    1. 前往目标文件夹

    这个文件夹是你用来保存虚拟环境的文件夹,该文件夹一旦确定就不要轻易更改。

    image-20190103154126721

    这个 py3-env1是创建的一个纯净虚拟环境。

    1. 创建纯净的虚拟环境
    virtualenv 虚拟环境名 (py3-env2)
    
    1. 终端启动虚拟环境
    cd py3-env1Scripts
    activate
    
    1. 进入虚拟环境下的 python 开发环境
    python3
    
    1. 关闭虚拟环境
    deactivate
    
    1. Pycharm的开发配置
    添加:创建项目 -> Project Interpreter -> Existing interpreter -> Virtualenv Environment | System Interpreter -> 目标路径下的 python.exe
    删除:Setting -> Project -> Project Interpreter -> Show All
    

    mac 电脑从第三步直接到最后一步就好

    了解

    # 创建非纯净环境:
    #	-- virtualenv-clone 本地环境 虚拟环境名
    
    # Mac配置终端,在终端运行虚拟环境
    # 在用户根目录下的.bash_profile(没有需手动创建)文件中设置
    # alias 终端指令名(env-py3)='/Library/Virtualenv/虚拟环境名/bin/python3'
    # alias 终端指令名(env-pip3)='/Library/Virtualenv/虚拟环境名/bin/pip3'
    

    HTTP 协议

    因为 Django 框架应用层是采用的 HTTP 协议,所以有必要了解 HTTP 协议。

    什么是 HTTP 协议

    • HTTP(HyperText Transport Protocol) 是超文本传输协议,而 HTTPS 也归属于 HTTP 协议,S 代表安全。
    • 基于 TCP/IP协议基础上的应用层协议,底层实现仍为 socket
    • 基于请求-响应模式:通信一定是从客户端开始,服务端接收到客户端一定会做出对应响应
    • 无状态:协议不对任何一次通信状态和任何数据做保存
    • 无连接:一次连接只完成一次请求-响应,请求-响应完毕后会立即断开连接。

    HTTP 工作原理

    一次 HTTP 连接称之为一个事务,过程可以分为四步

    1. 客户端与服务端建立连接
    2. 客户端发生一个 HTTP 协议指定格式的请求
    3. 服务端接收请求后,回应一个 HTTP 协议指定格式的响应
    4. 客户端将服务端的响应展现给用户

    HTTP 状态码

    • 1开头:

    • 2开头:

    • 3开头:

    • 4开头:

    • 5开头:

    请求报文

    # 请求行  请求头  请求体
    '''
    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
    '''
    

    响应报文

    # 响应行  响应头  响应体
    '''
    HTTP/1.1 200 OK
    
    Content-type:text/html
    
    
    
    Login Success
    '''
    

    使用原生 socket 完成和浏览器的交互

    目录结构

    01_socket
    	-- 01_client.html:前台通过form表单访问后台的页面
    	-- 01_login.html:后台测试渲染给前台的登录页面
    	-- 01_index.html:后台测试渲染给前台的主页
    	-- 01_server.py:后台服务器文件
    

    因为 B/S架构的客户端已经由浏览器写好,所以只需要关注服务器端就ok。

    服务器端代码

    from socket import socket
    
    # 设置响应头(包含响应行)
    RESP_HEADER = b'HTTP/1.1 200 OK
    Content-type:text/html;charset=utf-8
    
    ' # 连续两个
    表示响应头结束
    
    # 设置服务器 socket 相关信息
    server = socket()
    server.bind('', 8080) # 空字符串表示绑定本机
    server.listen(5)
    print(('服务:http://localhost:8080'))
    
    while True:
        # 获取以 http 协议发来的请求
        client, addr = server.accept()
        data = client.recv(1024)
        # 数据报文 包含请求行 请求头 请求体
        print(data)
        client.send(RESP_HEADER)
        
        # /index => 响应主页
        # /login => 登录页面
        # 错误 => 404
        # 数据 data, 字节形式 => 字符串形式
        strData = str(data, encodeing)
        
        # 解析请求的数据,分析得到路由
        my_route = strData.split('
    ')[0].split(' ')[1]
        
        # 后台没有设置的路由,统统由404来处理
        dt = b'404'
        
        # 设置的路由返回响应的页面文件
        if my_route == '/index':
            with open('index 页面路径', 'rb') as f:
                dt = f.read()
        if my_route == '/login':
            with open('login 页面路径', 'rb') as f:
                dt = f.read()
                
        # /favicon.ico该请求是往后台请求标签图标
        if my_route == '/favicon.ico':
            with open('favicon.ico', 'rb') as f:
                dt = f.read()
        # 服务器发送响应体
        client.send(dt)
        # 一次循环,代表一次响应,也就是一次事务的完成,要关闭 http 请求连接
        client.close()
    

    修改返回数据,完善响应体

    # 字符串
    client.send(b'HTTP/1.1 200 OK
    ')
    client.send(b'
    ')
    client.send(b'Normal Socket Web')
    
    # html代码,请求头要设置支持 html 代码
    client.send(b'HTTP/1.1 200 OK
    ')
    client.send(b'Content-type:text/html
    ')
    client.send(b'
    ')
    client.send(b'<h1>Normal Socket Web</h1>')
    
    # html文件(同级目录建立一个index.html页面)
    client.send(b'HTTP/1.1 200 OK
    ')
    client.send(b'Content-type:text/html
    ')
    client.send(b'
    ')
    # 利用文件方式读取页面
    with open('01_index.html', 'rb') as f:
        dt = f.read()
    client.send(dt)
    

    拓展

    修改接收数据,模拟后台路由

    # 分析接收到的数据
    data = client.recv(1024)
    # 保证接收到的数据作为字符串进行以下处理
    data = str(data, encoding='utf-8')
    # 拆分出地址位
    route = data.split('
    ')[0].split(' ')[1]
    # 匹配地址,做出不同的响应
    if route == '/index':
        with open('01_index.html', 'rb') as f:
        	dt = f.read()
    elif route == '/login':
        with open('01_login.html', 'rb') as f:
        	dt = f.read()
    else:
        dt = b'404'
    client.send(dt)
    

    框架演变

    目录结构

    02_frame
    	-- favicon.ico
    	-- index.html
    	-- manage.py
    

    manage.py

    import socket
    import pymysql
    # 响应头
    RESP_HEADER = b'HTTP/1.1 200 OK
    Content-type:text/html
    
    '
    
    # 请求处理
    def index():
        # 以字节方式读取文件
        with open('index.html', 'rb') as f:
            dt = f.read()
        return dt
    def ico():
        with open('favicon.ico', 'rb') as f:
            dt = f.read()
        return dt
    def user():
        # 数据库操作
        conn = pymysql.connect(host='127.0.0.1', port=3306, db='django', user='root', password='root')
        cur = conn.cursor(pymysql.cursors.DictCursor)
        cur.execute('select * from user')
        users = cur.fetchall()
        print(users)
        users = '''%d:%s
        %d:%s''' % (users[0]['id'], users[0]['name'], users[1]['id'], users[1]['name'])
        return users.encode('utf-8')
    
    # 设置路由
    urls = {
        # 请求路径与请求处理函数一一对应
        '/index': index,
        '/favicon.ico': ico,
        '/user': user
    }
    
    # 设置socket
    def serve(host, port):
        server = socket.socket()
        server.bind((host, port))
        print('start:http://' + host + ':' + str(port))
        server.listen(5)
        while True:
            sock, addr = server.accept()
            data = sock.recv(1024)
            data = str(data, encoding='utf-8')
            print(data)
            route = data.split('
    ')[0].split(' ')[1]
    
            resp = b'404'
            if route in urls:
                resp = urls[route]()
    
            sock.send(RESP_HEADER)
            sock.send(resp)
            sock.close()
    
    # 启服务
    if __name__ == '__main__':
        serve('127.0.0.1', 8002)
    

    项目演变

    目录结构

    03_proj
    	-- template
    		-- index.html
    		-- user.html
    	favicon.ico
    	start.py
    	urls.py
    	views.py
    

    index.html

    <h1>{{ name }}</h1>
    

    user.html

    <table border="1">
        <tr>
            <th>id</th>
            <th>name</th>
            <th>password</th>
        </tr>
        {% for user in users%}
        <tr>
            <td>{{user.id}}</td>
            <td>{{user.name}}</td>
            <td>{{user.password}}</td>
        </tr>
        {% endfor %}
    </table>
    

    start.py

    from wsgiref.simple_server import make_server
    from urls import urls
    
    
    def app(env, response):
        print(env)
        # 设置响应头
        response("200 OK", [('Content-type', 'text/html')])
        route = env['PATH_INFO']
        print(route)
        data = urls['error']()
        if route in urls:
            data = urls[route]()
        # 返回二进制响应体
        return [data]
    
    
    if __name__ == '__main__':
        server = make_server('127.0.0.1', 8003, app)
        print('start:http://127.0.0.1:8003')
        server.serve_forever()
    

    urls.py

    from views import *
    urls = {
        '/index': index,
        '/favicon.ico': ico,
        '/user': user,
        'error': error
    }
    

    views.py

    import pymysql
    # 利用jinja2来渲染模板,将后台数据传给前台
    from jinja2 import Template
    
    def index():
        with open('templates/index.html', 'r') as f:
            dt = f.read()
        tem = Template(dt)
        resp = tem.render(name='主页')
        return resp.encode('utf-8')
    
    def ico():
        with open('favicon.ico', 'rb') as f:
            dt = f.read()
        return dt
    
    def user():
        # 数据库操作
        conn = pymysql.connect(host='127.0.0.1', port=3306, db='django', user='root', password='root')
        cur = conn.cursor(pymysql.cursors.DictCursor)
        cur.execute('select * from user')
        users = cur.fetchall()
        print(users)
    
        with open('templates/user.html', 'r') as f:
            dt = f.read()
        tem = Template(dt)
        resp = tem.render(users=users)
    
        return resp.encode('utf-8')
    
    def error():
        return b'404'
    
  • 相关阅读:
    [Tutorial] How to check and kill running processes in Ubuntu
    [Tutorial] Getting started with Gazebo in ROS
    Linux基础命令
    Linux安装系统
    vue 前后端数据交互问题解决
    如何在cmd中启动MongoDB服务器和客户端
    selenuim模块的使用 解析库
    beautifhulsoup4的使用
    浅谈scrapy框架安装使用
    自动登录 点赞 评论 抽屉网
  • 原文地址:https://www.cnblogs.com/zuanzuan/p/10215998.html
Copyright © 2020-2023  润新知