Django前置知识--手撕框架(二)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: Django前置知识--手撕框架(二)

Django前置知识--手撕框架(一):https://developer.aliyun.com/article/1495494

重启服务端,浏览器再次访问,页面内容有了,样式效果也有了

检查查看application里面该有的数据也都有了,浏览器可以正常渲染页面了

浏览器检查network里面的筛选,可以看到浏览器的各种文件请求,以及服务器响应耗时

每个文件点进去,可以查看具体请求信息和响应

请求

响应

这种方法比较low,如果网站页面比较多的话,客户端请求比较多,一个一个判断,说不过去。开发中,尽量少用多层判断,判断越少越好

需要改进

函数版

import socket

#改造服务端,针对客户端不同的请求,服务端回复不同的内容
tcp_server = socket.socket()
#端口复用
tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
tcp_server.bind(("127.0.0.1",8898))
tcp_server.listen(128)

#首先先将页面信息封装成函数,返回相关页面文件信息流
def html():
    with open("beautiful.html", "rb") as fp:
        data = fp.read()
    return data

def css():
    with open("xx.css", "rb") as fp:
        data = fp.read()
    return data

def jpg():
    with open("1.jpg", "rb") as fp:
        data = fp.read()
    return data

def js():
    with open("xx.js", "rb") as fp:
        data = fp.read()
    return data

#将函数与请求对应
urlpath = [
    ("/",html),
    ("/xx.css",css),
    ("/1.jpg",jpg),
    ("/xx.js",js),
]


while True:
    # 获取连接对象和客户端ip和端口
    conn,adddr = tcp_server.accept()
    # 接收客户端数据
    res = conn.recv(1024)
    from_broswer = res.decode()
    print(from_broswer)
    #根据请求头 GET / HTTP/1.1  以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容
    path = from_broswer.split()[1]
    # 针对不同请求赋值不同页面数据,发送个客户端
    for i in urlpath:
        if path == i[0]:
            data = i[1]()
            break

    # 发送协议数据
    strvar = "HTTP/1.1 200 0k\r\n\r\n"
    conn.send(strvar.encode())
    # 发送给客户端页面
    conn.send(data)
    conn.close()

#tcp_server.close();

但是该页面都是静态页面,下面做个动态页面

html页面加个h1标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>个人中心</title>
    <link rel="stylesheet" href="xx.css">

</head>
<body>
    <h1>欢迎来到32期spa会所</h1>
    <h1>%时间%</h1>
    <div class="c1"></div>
    <img src="1.jpg" alt="">
</body>
<script src="xx.js"></script>
</html>

在服务端,将页面上的 %时间% 替换为一个动态获取的时间戳

时间戳默认是float

import socket
import time

#改造服务端,针对客户端不同的请求,服务端回复不同的内容,动态页面版
tcp_server = socket.socket()
#端口复用
tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
tcp_server.bind(("127.0.0.1",8898))
tcp_server.listen(128)

#展示动态页面,以r的形式读取
def html():
    将时间戳转换成字符串,时间戳默认是float类型
    now = str(time.time())
    with open("beautiful.html", "r",encoding="utf-8") as fp:
        data = fp.read()
    在这里将页面上的 %时间% 替换为动态的时间戳
    data = data.replace("%时间%",now).encode()
    return data

def css():
    with open("xx.css", "rb") as fp:
        data = fp.read()
    return data

def jpg():
    with open("1.jpg", "rb") as fp:
        data = fp.read()
    return data

def js():
    with open("xx.js", "rb") as fp:
        data = fp.read()
    return data

#将函数与请求对应
urlpath = [
    ("/",html),
    ("/xx.css",css),
    ("/1.jpg",jpg),
    ("/xx.js",js),
]


while True:
    # 获取连接对象和客户端ip和端口
    conn,adddr = tcp_server.accept()
    # 接收客户端数据
    res = conn.recv(1024)
    from_broswer = res.decode()
    print(from_broswer)
    #根据请求头 GET / HTTP/1.1  以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容
    path = from_broswer.split()[1]
    # 针对不同请求赋值不同页面数据,发送个客户端
    for i in urlpath:
        if path == i[0]:
            data = i[1]()
            break

    # 发送协议数据
    strvar = "HTTP/1.1 200 0k\r\n\r\n"
    conn.send(strvar.encode())
    # 发送给客户端页面
    conn.send(data)
    conn.close()

#tcp_server.close();

但这只是单个页面网站,人家网站都有好多页面可以跳转,需要改造

2、多页面网站框架

我们的之所以是单页面,原因就是只有一个beautiful.html

要实现多页面,多添加几个html页面即可

我们新加一个person.html

服务端将页面添加进去,其他不变

浏览器访问,可以跳转到指定页面

我们可以在主页面做个页面跳转

<!--    页面跳转,相对路径,当点击该链接时,浏览器拼接请求url http://127.0.0.1:8898/person  实现页面跳转-->

重启服务器,浏览页面

点击跳转,实现想要结果

现在,请求时异步的,但服务端是客户端来了一个个请求,建立连接,收发数据,断开连接,下次请求过来,又重新建立连接…

服务端是同步的,不能异步回复

客户端异步发送的请求,异步回复多好,需要改进

3、多线程并发服务端框架

import socket
import time
from threading import Thread

#多线程编程,服务端实现异步回复客户端
tcp_server = socket.socket()
#端口复用
tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
tcp_server.bind(("127.0.0.1",8898))
tcp_server.listen(128)

#每个函数自己发送数据给客户端,发送完毕自己断开连接。每个函数是一个线程
def html(conn):
    now = str(time.time())
    with open("beautiful.html", "r",encoding="utf-8") as fp:
        data = fp.read()
    data = data.replace("%时间%",now).encode()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

def css(conn):
    with open("xx.css", "rb") as fp:
        data = fp.read()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

def jpg(conn):
    with open("1.jpg", "rb") as fp:
        data = fp.read()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

def js(conn):
    with open("xx.js", "rb") as fp:
        data = fp.read()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

#添加个页面
def person(conn):
    with open("person.html", "rb") as fp:
        data = fp.read()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

#将函数与请求对应,将person加入
urlpath = [
    ("/",html),
    ("/xx.css",css),
    ("/1.jpg",jpg),
    ("/xx.js",js),
    ("/person",person)
]

#多线程编程
if __name__ == '__main__':
    while True:
        # 获取连接对象和客户端ip和端口
        conn,adddr = tcp_server.accept()
        # 接收客户端数据
        res = conn.recv(1024)
        from_broswer = res.decode()
        print(from_broswer)
        #根据请求头 GET / HTTP/1.1  以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容
        path = from_broswer.split()[1]
        # 针对不同请求赋值不同页面数据,发送个客户端
        # 发送协议数据
        strvar = "HTTP/1.1 200 0k\r\n\r\n"
        conn.send(strvar.encode())
        # 针对每个请求,采用一个线程
        for i in urlpath:
            if path == i[0]:
                针对每个页面请求,创建一个线程,将连接作为参数传给函数
                t = Thread(target=i[1],args=(conn,))
                t.start()
                break


    # tcp_server.close();

多线程,理论上更快了。我们的页面比较小,体现不出来

现在,我们每个功能都在一个文件里面,当业务量比较庞大时,就比较冗余

因此,我们需要做功能拆分

1、manager

import socket
from threading import Thread
import urls


#多线程编程,服务端实现异步回复客户端
tcp_server = socket.socket()
#端口复用
tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
tcp_server.bind(("127.0.0.1",8898))
tcp_server.listen(128)



#多线程编程
if __name__ == '__main__':
    while True:
        # 获取连接对象和客户端ip和端口
        conn,adddr = tcp_server.accept()
        # 接收客户端数据
        res = conn.recv(1024)
        from_broswer = res.decode()
        print(from_broswer)
        #根据请求头 GET / HTTP/1.1  以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容
        path = from_broswer.split()[1]
        # 针对不同请求赋值不同页面数据,发送个客户端
        # 发送协议数据
        strvar = "HTTP/1.1 200 0k\r\n\r\n"
        conn.send(strvar.encode())
        # 针对每个请求,采用一个线程
        for i in urls.urlpath:
            if path == i[0]:
                t = Thread(target=i[1],args=(conn,))
                t.start()
                break

    # tcp_server.close();

2、urls

import views
#将函数与请求对应,将person加入
urlpath = [
    ("/",views.html),
    ("/static/xx.css",views.css),
    ("/static/1.jpg",views.jpg),
    ("/static/xx.js",views.js),
    ("/person",views.person)
]

3、views

import time
#展示动态页面,以r的形式读取
def html(conn):
    now = str(time.time())
    with open("templates/beautiful.html", "r", encoding="utf-8") as fp:
        data = fp.read()
    data = data.replace("%时间%",now).encode()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

def css(conn):
    with open("static/xx.css", "rb") as fp:
        data = fp.read()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

def jpg(conn):
    with open("static/1.jpg", "rb") as fp:
        data = fp.read()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

def js(conn):
    with open("static/xx.js", "rb") as fp:
        data = fp.read()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

#添加个页面
def person(conn):
    with open("templates/person.html", "rb") as fp:
        data = fp.read()
    # 发送给客户端页面
    conn.send(data)
    conn.close()

templates目录下存放html文件

beatuiful.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>个人中心</title>
    <link rel="stylesheet" href="../static/xx.css">

</head>
<body>
    <h1>欢迎来到32期spa会所</h1>
    <!--    页面跳转,相对路径,当点击该链接时,浏览器拼接请求url http://127.0.0.1:8898/person  实现页面跳转-->
    <a href="/person">个人中心</a>
    <h1>%时间%</h1>
    <div class="c1"></div>
    <img src="../static/1.jpg" alt="">
</body>
<script src="../static/xx.js"></script>
</html>

person.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>个人中心</title>

</head>
<body>
    <h1>这是个人中心页面</h1>
</body>
</html>

static目录下存放css,js,图片文件等静态文件

可以创建个文件连接数据库

models.py

import pymysql

def MySqlInfo():
    conn = pymysql.connect(
        host="10.10.0.52",
        port=3306,
        database="kuangjia",
        charset="utf8mb4",
        user="root",
        password="Jinghao31357@"
    )

    cur = conn.cursor(cursor=pymysql.cursors.DictCursor)
    try:
        sql = "create table userinfo(id int primary key auto_increment, name char(10) not null, age int unsigned);"
        cur.execute(sql)
        print("创建表成功")
    except BaseException as e:
        print("有异常,执行失败",e)
    finally:
        #pymysql默认是不提交的,手动设置每次执行后提交
        conn.commit()
        cur.close()
        conn.close()

创建个wsgi存放我们的manager.py核心代码,并封装成一个函数里面,其他不用动

在manager.py文件中编写代码运行方式

import sys

from wsgi import run
from models import MySqlInfo

commands = sys.argv

tasks = commands[1]

#运行项目的指令: python manage.py runserver
#数据库同步指令: python manage.py migrate
if tasks == "runserver":
    run()
elif tasks == "migrate":
    MySqlInfo()

1、配置路径对应的函数关系 urls.py文件中,有参考案例

2、在views.py中,写视图函数

3、templates文件夹中创建html文件

框架开发出来不是给客户用的,是给程序员使用的

然后写个readme

比如我们这个框架,各个模块拆分,就比较清晰了。这就是django的雏形

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7天前
|
缓存 安全 API
Django框架
【5月更文挑战第5天】Django是Python的高效Web框架,适合构建各种规模的Web应用。本指南逐步介绍Django核心概念和高级特性,包括安装、创建项目和应用、视图、URL路由,以及数据库模型、管理后台、用户认证。还涉及RESTful API、缓存、性能优化、国际化、测试、异步任务、Web套件、Django Channels和定时任务。通过学习,开发者能全面掌握Django并构建高性能应用。
17 3
|
13天前
|
JSON 前端开发 网络架构
Django的web框架Django Rest_Framework精讲(四)
Django的web框架Django Rest_Framework精讲(四)
|
13天前
|
前端开发 数据库 网络架构
Django的web框架Django Rest_Framework精讲(三)
Django的web框架Django Rest_Framework精讲(三)
|
13天前
|
前端开发 数据库 数据安全/隐私保护
Django的web框架Django Rest_Framework精讲(二)
Django的web框架Django Rest_Framework精讲(二)
|
13天前
|
JSON 前端开发 数据库
Django的web框架Django Rest_Framework精讲(二)
Django的web框架Django Rest_Framework精讲(二)
|
13天前
|
JSON API 数据库
Django的web框架Django Rest_Framework精讲(一)
Django的web框架Django Rest_Framework精讲(一)
|
14天前
|
Oracle 关系型数据库 MySQL
Django框架ORM操作(二)
Django框架ORM操作(二)
|
14天前
|
SQL 存储 前端开发
Django框架ORM操作(一)
Django框架ORM操作(一)
Django框架ORM操作(一)
|
14天前
|
JSON 前端开发 Linux
Django框架初探
Django框架初探
|
14天前
|
Web App开发 JavaScript 数据格式
Django前置知识--手撕框架(一)
Django前置知识--手撕框架(一)