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

简介: Django前置知识--手撕框架(一)

手撕框架

在学Django之前,我们先手撸一个简单的socket框架出来

通过对socket的学习,我们知道网络通信,我们完全可以自己写了,因为socket就是做网络通信用的,

下面我们就基于socket来自己实现一个web框架,写一个web服务端,让浏览器来请求,并通过自己的服务端把页面返回给浏览器,浏览器渲染出我们想要的效果。

web框架的本质及自定义web框架

 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端,

基于请求做出响应,客户都先请求,服务端做出对应的响应,按照http协议的请求协议发送请求,

服务端按照http协议的响应协议来响应请求,这样的网络通信,我们就可以自己实现Web框架了。

通过对socket的学习,我们知道网络通信,我们完全可以自己写了,因为socket就是做网络通信用的,

下面我们就基于socket来自己实现一个web框架,写一个web服务端,让浏览器来请求,并通过自己的服务端把页面返回给浏览器,浏览器渲染出我们想要的效果

1、tcp_server端

import socket
tcp_server = socket.socket()
#端口复用
tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
tcp_server.bind(("127.0.0.1",8898))   #绑定本地8898端口,后续用浏览器访问
tcp_server.listen(128)
#获取连接对象和客户端ip和端口
while True:
    conn,adddr = tcp_server.accept()

    # 接收数据
    res = conn.recv(1024)
    print(res.decode())
    # 发送数据
    strvar = "need server?"
    conn.send(strvar.encode())
    conn.close()

#tcp_server.close();

浏览器访问:不通

浏览器访问服务器,会发送http请求报文格式到服务端,在服务端打印

GET / HTTP/1.1 #请求方法,请求协议版本号

Host: 127.0.0.1:8898 #请求服务器的ip和端口

Connection: keep-alive #是否长连接

sec-ch-ua: “Chromium”;v=“112”, “Google Chrome”;v=“112”, “Not:A-Brand”;v=“99”

sec-ch-ua-mobile: ?0

sec-ch-ua-platform: “Windows”

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7

Sec-Fetch-Site: none

Sec-Fetch-Mode: navigate

Sec-Fetch-User: ?1

Sec-Fetch-Dest: document

Accept-Encoding: gzip, deflate, br

Accept-Language: zh-CN,zh;q=0.9

但我们服务端是基于socket写的,没写应用层协议,因此要写基于http协议的数据格式响应客户端

现在服务端回应客户端只有一句二进制的 need server ?

客户端根本解不开,因此客户端会报错,无效响应。

回应的时候要把回应的数据格式加工好,再发出去

改造服务端

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)
#获取连接对象和客户端ip和端口
while True:
    conn,adddr = tcp_server.accept()
    res = conn.recv(1024)
    print(res.decode())
    # 发送数据,这是基于HTTP协议的报文格式
    strvar = "HTTP/1.1 200 0k\r\n\r\nneed server?"
    conn.send(strvar.encode())
    conn.close()

#tcp_server.close();

此时在通过浏览器访问,就收到服务端信息

现在回复给客户端的是简单的字符串,正常的应该回复页面才对

先创建个简单的页面

<!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>欢迎来到32期spa会所</h1>

</body>
</html>

在服务端通过http协议发送给客户端

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)
#获取连接对象和客户端ip和端口
while True:
    conn,adddr = tcp_server.accept()
    # 接收客户端数据
    res = conn.recv(1024)
    print(res.decode())



    with open("beautiful.html","rb") as fp:
        data = fp.read()
    # 发送协议数据
    strvar = "HTTP/1.1 200 0k\r\n\r\n"
    conn.send(strvar.encode())
    # 发送给客户端页面
    conn.send(data)
    conn.close()

#tcp_server.close();

客户端访问,已收到服务端发来的页面

给页面添加点样式和动画效果

<!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>
    <div class="c1"></div>
    <img src="1.jpg" alt="">
</body>
<script src="xx.js"></script> #引入外部js
</html>

重新运行服务器,在浏览器访问,样式也引入了,js也引入了,但是却不显示效果

这是为啥呢,这是因为浏览器对html从上往下解析

当解析到link时,由于写的是相对路径,

浏览器会从当前浏览器路径

127.0.0.1:8898/xx.css 查找,去请求后台,拿这个文件。

但却没找到,异步发了几个请求

请求 xx.css 1.jpg xx.js 都没找到,所以样式显示不出来

查看客户端请求

点击xx.css,查看请求详情

后台没给浏览器发数据,浏览器拿不到数据就无法渲染代码

浏览器打开网页 另存为

会将本页面的html代码 和外部引入的js文件css文件等都存到本地

这样,在本地通过浏览器访问该页面才能正常显示

本地访问,就相当于上网访问一样的显示效果

浏览器查看网页文件 检查–application-top。里面都有

如果把一块下载下来的js,css文件删除,那么本地访问,也将少了样式

我们自己搭的服务器,通过浏览器访问页面,没样式相当于上面另存为本地的html文件,样式被删除了

所以访问没有样式

客户端发来的请求

请求方法后面是请求路径,当我们访问url只接端口号,后面也没接的时候,请求的就是根路径

然后是要各种外部加载文件的请求

客户端请求什么数据,服务端就应该给客户端什么数据。

服务端要把对应的数据给响应回去,根据客户端的请求,要什么,就响应什么回去

服务端循环回应客户端数据,每次都是一样的,html页面

目前我们服务端的做法是,客户端一次请求,服务端回应一个数据,断开连接

客户端再次请求,服务端又响应一个数据,断开连接

但每次客户端请求的数据不一样,但服务端回应的数据却是一样的,都是html页面

显然这样是不合理的

应该根据不同的请求回复不同的数据

分析:每次请求,就GET后面的路径不一样

我们可以基于不同的路径回复不同的数据

服务端改造如下

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)


while True:
    # 获取连接对象和客户端ip和端口
    conn,adddr = tcp_server.accept()
    # 接收客户端数据
    res = conn.recv(1024)
    from_broswer = res.decode()
    #重点在这里,根据客户端请求头 GET / HTTP/1.1  可知,以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容
    path = from_broswer.split()[1]

  做逻辑判断,针对不同请求,回复给客户端不同数据
   if path == "/":
        with open("beautiful.html", "rb") as fp:
            data = fp.read()
    elif path == "/xx.css":
        with open("xx.css", "rb") as fp:
            data = fp.read()
    elif path == "/1.jpg":
        with open("1.jpg", "rb") as fp:
            data = fp.read()
    elif path == "/xx.js":
        with open("xx.js", "rb") as fp:
            data = fp.read()

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

#tcp_server.close();

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

相关文章
|
17小时前
|
存储 缓存 安全
Django的会话框架提供了一种简单且安全的方式来在用户与网站之间存储和检索状态信息
【5月更文挑战第12天】Django的会话管理依赖于内置的SessionMiddleware。要启用,需在settings.py的MIDDLEWARE中包含它,并确保&#39;django.contrib.sessions&#39;在INSTALLED_APPS内。设置SESSION_ENGINE可选择存储引擎,如默认的数据库或缓存。在视图中,通过request.session交互会话数据。模板可以直接访问这些数据。配置包括会话超时、cookie属性和存储后端。注意,敏感数据不宜存入会话,确保会话cookie安全,考虑使用缓存降低数据库压力。
7 3
|
8天前
|
缓存 安全 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框架初探