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
相关文章
|
8天前
|
中间件 数据库 数据安全/隐私保护
Django框架的深入探索与实践
本文介绍了Django,一个流行的Python Web框架,以其优雅设计和强大功能吸引开发者。Django遵循MVC模式,提供URL路由、模板引擎和ORM等核心组件,强调高效简洁的开发方式。文中详细阐述了Django的安装配置过程,核心组件包括URL路由、视图模板和模型ORM。此外,还探讨了Django的表单处理、用户认证、中间件和信号等进阶应用。Django凭借其不断发展的特性和全面的Web开发解决方案,持续受到开发者的青睐。【6月更文挑战第8天】
13 4
|
23天前
|
缓存 API 数据库
Django中的REST框架
【5月更文挑战第20天】Django的REST框架使得在Python中构建和管理API变得简单。本文详细介绍了如何使用Django REST框架,从安装库到创建简单的用户API,包括模型、序列化器、视图集和路由配置。此外,还讨论了REST原则、认证、权限控制、响应格式定制、分页过滤、数据验证、错误处理、测试、文档、异步视图、性能优化、安全性、版本控制、迁移、数据序列化、文件上传、身份验证、授权、响应定制、错误处理、性能监控、缓存和测试。Django REST框架为高效API开发提供了全面支持。
30 3
|
23天前
|
存储 设计模式 前端开发
Python Django框架总介绍
Python Django框架总介绍
16 0
|
26天前
|
设计模式 缓存 前端开发
Python Django框架
Python Django框架
|
30天前
|
缓存 监控 安全
Django框架在大型Web应用中的架构设计与实战
【5月更文挑战第18天】Django框架在构建大型Web应用中扮演重要角色,采用分层架构(数据、业务逻辑、表示层)和多应用组织模式,结合缓存策略(如Memcached、Redis)提升性能。通过异步处理、分布式部署提高响应速度和扩展性。关注数据分区、安全设计及监控日志,确保系统高效、稳定。Django为复杂业务提供坚实基础,助力打造卓越Web系统。
50 7
|
30天前
|
缓存 数据处理 数据库
Django 框架高级进阶:探索最佳实践与性能优化
【5月更文挑战第18天】在Django开发中,掌握高级技巧和性能优化是关键。最佳实践包括合理组织代码结构、数据库设计优化、使用信号机制和缓存策略。性能优化涉及数据库查询优化(如select_related和prefetch_related)、异步任务处理(如Celery)、启用HTTP缓存、优化模板渲染和服务器配置调整。示例中,通过分页减少数据加载量以提高性能。不断探索和应用这些方法能提升用户体验,应对高并发和大规模数据挑战。
37 6
|
30天前
|
开发框架 中间件 数据库
Django 框架入门全攻略:轻松构建 Web 应用
【5月更文挑战第18天】本文是 Django 入门教程,介绍了如何使用 Django 构建 Web 应用。内容包括安装、项目与应用创建、模型定义、数据库迁移、视图编写、路由配置、模板系统、表单处理和中间件的使用。通过实例展示了 Django 基本流程,帮助初学者快速上手。Django 提供高效工具,便于开发者聚焦业务逻辑,轻松构建功能丰富的 Web 应用。
42 5
|
1月前
|
存储 缓存 安全
Django的会话框架提供了一种简单且安全的方式来在用户与网站之间存储和检索状态信息
【5月更文挑战第12天】Django的会话管理依赖于内置的SessionMiddleware。要启用,需在settings.py的MIDDLEWARE中包含它,并确保&#39;django.contrib.sessions&#39;在INSTALLED_APPS内。设置SESSION_ENGINE可选择存储引擎,如默认的数据库或缓存。在视图中,通过request.session交互会话数据。模板可以直接访问这些数据。配置包括会话超时、cookie属性和存储后端。注意,敏感数据不宜存入会话,确保会话cookie安全,考虑使用缓存降低数据库压力。
37 3
|
1月前
|
缓存 安全 API
Django框架
【5月更文挑战第5天】Django是Python的高效Web框架,适合构建各种规模的Web应用。本指南逐步介绍Django核心概念和高级特性,包括安装、创建项目和应用、视图、URL路由,以及数据库模型、管理后台、用户认证。还涉及RESTful API、缓存、性能优化、国际化、测试、异步任务、Web套件、Django Channels和定时任务。通过学习,开发者能全面掌握Django并构建高性能应用。
23 3
|
1月前
|
JSON 前端开发 网络架构
Django的web框架Django Rest_Framework精讲(四)
Django的web框架Django Rest_Framework精讲(四)