目录

1.web框架理解
     2.http工作原理
     3.通过函数实现浏览器和服务端通信案例
     4.服务器程序和引用程序理解
     5.jinja2渲染模板案例
     6.Django简单说明

Web框架的本质

web应用本质上就是一个socket服务端,而浏览器就是一个socket客户端,这样就可以实现web框架了

socket web服务器

import socket
server = socket.socket()
server.bind(('127.0.0.1',8000))
server.listen()
while True:
conn, addr = sk.accept()
data = conn.recv(8096)
conn.send(b"OK")
conn.close()

http协议规定了浏览器发送消息或者服务器回复消息都要按照它规定来写

执行上面那段代码print(data)会得到以下结果

将\r\n替换成换行后的结果

GET / HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3355.4 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
Cookie: csrftoken=CtHePYARJOKNx5oNVwxIteOJXpNyJ29L4bW4506YoVqFaIFFaHm0EWDZqKmw6Jm8

访问博客园返回浏览器的信息

由此可见首发信息都是按照一定格式来的,所以需要了解http协议工作模式

Http工作原理:

HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,
请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。 以下是 HTTP 请求/响应的步骤: 1. 客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.luffycity.com。 2. 发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。 3. 服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。 4. 释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,
在该时间内可以继续接收请求; 5. 客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,
根据HTML的语法对其进行格式化,并在浏览器窗口中显示。 在浏览器地址栏键入URL,按下回车之后会经历以下流程: 1.浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
2.解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
2.浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
4.服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
5.释放 TCP连接;
6.浏览器将该 html 文本并显示内容;

  

http请求格式

http响应格式:

通过函数实现浏览器和服务端通信案例

自定义web框架按照http格式发送响应并根据url中的路径返回不同的内容

import socket
server = socket.socket()
server.bind(('127.0.0.1',8000))
server.listen()
while True:
conn,addr = server.accept()
data = conn.recv(1024)
data = data.decode('utf-8')
print(data) url = data.split()[1]
if url == '/home/':
conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>home<h1>')
elif url == '/index/':
conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>index<h1>')
else:
conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>404 not found<h1>')
conn.close()

基于函数实现url不同路径返回不同内容

import socket
server = socket.socket()
server.bind(('127.0.0.1',8000))
server.listen() def func(url):
s = f"this is {url} page"
return bytes(s,encoding="utf-8") while True:
conn,addr = server.accept()
data = conn.recv(8096)
data = str(data,encoding="utf-8")
print(data)
data1= data.split("\r\n")[0]
url = data1.split()[1] conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>ok<h1>') 这个地方需要注意的一个点 闭合标签不能写/ 否则就当成普通字符串进行处理
if url == "/index/":
response = func(url)
elif url == "/home/":
response = func(url)
else:
response = b"404 not found" conn.send(response)
conn.close()

实现url不同路径返回不同内容函数进阶版

import socket
server =socket.socket()
server.bind(('127.0.0.1',8000))
server.listen() def index(url):
s = f"This is {url} page"
return bytes(s,encoding="utf-8") def home(url):
s = f"This is {url} page"
return bytes(s,encoding="utf-8") list1 = [("/index/",index),
("/index/",home)] while True:
conn,addr = server.accept()
data = conn.recv(8096)
data = str(data,encoding="utf-8")
print(data)
data1= data.split("\r\n")[0]
url = data1.split()[1]
conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>ok<h1>')
func = None
for item in list1:
if item[0] == url:
func = item[1]
break
if func:
response = func(url)
else:
response = b"404 not found"
conn.send(response)
conn.close()

返回具体的html文件

import socket
server =socket.socket()
server.bind(('127.0.0.1',8000))
server.listen() def index(url):
with open("template/index.html","r",encoding="utf-8") as f:
s = f.read()
return bytes(s,encoding="utf-8") def home(url):
with open("template/home.html", "r", encoding="utf-8") as f:
s = f.read()
return bytes(s,encoding="utf-8") list1 = [("/index/",index),
("/home/",home)] while True:
conn,addr = server.accept()
data = conn.recv(8096)
data = str(data,encoding="utf-8")
print(data)
data1= data.split("\r\n")[0]
url = data1.split()[1]
conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>ok<h1>')
func = None
for item in list1:
if item[0] == url:
func = item[1]
break
if func:
response = func(url)
else:
response = b"404 not found"
conn.send(response)
conn.close()

网页动态

import socket
server =socket.socket()
server.bind(('127.0.0.1',8000))
server.listen() def index(url):
with open("template/index.html","r",encoding="utf-8") as f:
s = f.read()
return bytes(s,encoding="utf-8") def home(url):
with open("template/home.html", "r", encoding="utf-8") as f:
s = f.read()
return bytes(s,encoding="utf-8") def timer(url):
import time
with open("template/timer.html","r",encoding="utf-8") as f:
s = f.read()
s = s.replace('@@time@@',time.strftime("%Y-%m-%d %H:%M:%S"))
return bytes(s,encoding="utf-8") list1 = [("/index/",index),
("/home/",home),
("/time/",timer)] while True:
conn,addr = server.accept()
data = conn.recv(8096)
data = str(data,encoding="utf-8")
print(data)
data1= data.split("\r\n")[0]
url = data1.split()[1]
conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>ok<h1>')
func = None
for item in list1:
if item[0] == url:
func = item[1]
break
if func:
response = func(url)
else:
response = b"404 not found"
conn.send(response)
conn.close()

服务器程序和应用程序

对于真实开发中的python web程序来说,一般会分为服务器程序和应用程序

服务器程序负责对socket服务端进行封装,并在请求到来时,对请求的各种数据进行处理

应用程序则负责处理具体的逻辑,为了方便应用程序开发,就出现了众多的web框架。

应用程序必须和服务程序配合才能为用户提供服务。

WSGI (Web Server Gateway Interface)是一种规范,定义了使用Python编写的Web应用程序与web服务程序之间的接口格式,实现了web应用程序和web服务程序间的解耦

常用的WSGI服务器有uWSGI、Gunicorn、而python标准库提供的WSGI叫wsgiref,Django开发环境用的就是这个模块来做的服务器。

wsgiref写web框架的socket server例子:

from wsgiref.simple_server import make_server

def index(url):
with open("template/index.html","r",encoding="utf-8") as f:
s = f.read()
return bytes(s,encoding="utf-8") def home(url):
with open("template/home.html", "r", encoding="utf-8") as f:
s = f.read()
return bytes(s,encoding="utf-8") def timer(url):
import time
with open("template/timer.html","r",encoding="utf-8") as f:
s = f.read()
s = s.replace('@@time@@',time.strftime("%Y-%m-%d %H:%M:%S"))
return bytes(s,encoding="utf-8") list1 = [("/index/",index),
("/home/",home),
("/time/",timer)]
#
def run_server(environ,start_response):
start_response('200 ok',[('Content-Type','text/html;charset=utf8'),])
url =environ['PATH_INFO']
func =None
for i in list1:
if i[0] == url:
func = i[1]
break
if func:
response = func(url)
else:
response = b'404 not found'
return [response,] if __name__ == '__main__':
httpd = make_server('127.0.0.1',8000,run_server)
print("I am waitting for you at 8000")
httpd.serve_forever()

使用jinja2渲染

python代码
from wsgiref.simple_server import make_server
from jinja2 import Template def index(url):
with open('template/index2.html',"r",encoding="utf-8") as f:
data = f.read()
template = Template(data) #生成模板
#把数据填充到模板中
ret = template.render({'name': 'xxx', 'hobby_list': ['抽烟', '喝酒', '烫头']})
return bytes(ret,encoding="utf-8") def home(url):
with open("home.html", "r", encoding="utf8") as f:
s = f.read()
return bytes(s, encoding="utf8") list1 = [
("/index/", index),
("/home/", home),
] def run_server(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息
url = environ['PATH_INFO'] # 取到用户输入的url
func = None
for i in list1:
if i[0] == url:
func = i[1]
break
if func:
response = func(url)
else:
response = b"404 not found!"
return [response, ] if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8090, run_server)
print("我在8090等你哦...")
httpd.serve_forever()

要渲染的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">
<title>Title</title>
</head>
<body>
<h1>姓名:{{name}}</h1>
<h1>爱好:</h1>
<ul>
{% for hobby in hobby_list %}
<li>{{hobby}}</li>
{% endfor %}
</ul>
</body>
</html>

Django简介

安装
pip3 install django==1.11.22 创建一个Django项目
django-admin startproject mysite02

目录简介
mysite/
├── manage.py # 管理文件
└── mysite # 项目目录
├── __init__.py
├── settings.py # 配置
├── urls.py # 路由 --> URL和函数的对应关系
└── wsgi.py # runserver命令就使用wsgiref模块做简单的web server 运行django项目
python manage.py runserver 127.0.0.1:8000

模板文件配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "template")], # template文件夹位置
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
] 静态文件配置
STATIC_URL = '/static/'  # HTML中使用的静态文件夹前缀
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"), # 静态文件存放位置
] 方便提交表单暂时禁用csrf中间件

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


Django基础三要素

from django.shortcuts import HttpResponse, render, redirect

HttpResponse 内部传入一个字符串参数,返回给浏览器
def index(request):
# 业务逻辑代码
return HttpResponse("OK") render
除request参数外还接受一个待渲染的模板和一个保存具体数据的字典参数
将数据填充进模板文件,最后把结果返回给浏览器(类似上面的jinja2)
def index(request):
# 业务逻辑代码
return render(request, "index.html", {"name": "xxx", "hobby": ["烫头", "泡吧"]}) redirect
接收一个URL参数,表示跳转到指定的URL
def index(request):
# 业务逻辑代码
return redirect("/home/")

此博客大部分内容是参考老师的,主要为了自己加深理解......

Web框架理解的更多相关文章

  1. web框架推导

    django 引言 所有的web应用本质上就是一个socket服务端,而用户的浏览器. 软件开发架构 cs架构 bs架构 本质上,bs架构也是cs架构 http协议 网络协议 http协议 数据传输是 ...

  2. 一步一步理解 python web 框架,才不会从入门到放弃

    要想清楚地理解 python web 框架,首先要清楚浏览器访问服务器的过程. 用户通过浏览器浏览网站的过程: 用户浏览器(socket客户端) 3. 客户端往服务端发消息 6. 客户端接收消息 7. ...

  3. 【译】什么是 web 框架?

    Web 应用框架,或者简单的说是“Web 框架”,其实是建立 web 应用的一种方式.从简单的博客系统到复杂的富 AJAX 应用,web 上每个页面都是通过写代码来生成的.我发现很多人都热衷于学习 w ...

  4. 第二篇 基于.net搭建热插拔式web框架(沙箱的构建)

    上周五写了一个实现原理篇,在评论中看到有朋友也遇到了我的问题,真的是有种他乡遇知己的感觉,整个系列我一定会坚持写完,并在最后把代码开源到git中.上一篇文章很多人看了以后,都表示不解,觉得不知道我到底 ...

  5. jS正则和WEB框架Django的入门

    JS正则 -test 判断字符串是否符合规定的正则表达式 -exec 获取匹配的数据 test的例子: 从上述的例子我们可以看出,如果rep.test匹配到了就返回true,否则返回false exe ...

  6. web框架思考

    以前一直不明白web框架是怎样实现路由.orm.接受请求的.今天看了下廖雪峰的python 实现web框架博客才明白. 简单总结并记录: http请求->wsgi->处理请求->返回 ...

  7. Python基础篇【第3篇】: Python异常处理、反射、动态导入、利用反射的web框架

    异常处理 什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当P ...

  8. 从零构建一个简单的 Python Web框架

    为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点: 你有一个新奇的想法,觉得将会取代其他的框架 你想要获得一些名气 你遇到的问题很独特,以至于现有的框架不太合适 你对 web 框架是如何 ...

  9. Spring 4 官方文档学习(十三)集成其他web框架

    重点是通用配置,非常建议看一下!有助于理解Spring的ApplicationContext与Servlet Container的关系! 1.介绍 Spring Web Flow SWF目标是成为we ...

随机推荐

  1. C++ STL——stack和queue

    目录 一 stack容器 二 queue容器 注:原创不易,转载请务必注明原作者和出处,感谢支持! 注:内容来自某培训课程,不一定完全正确! 栈和队列作为经典的数据结构,我们再熟悉不过了.C++ ST ...

  2. LC 377. Combination Sum IV

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  3. vuex中的babel编译mapGetters/mapActions报错解决方法

    vex使用...mapActions报错解决办法 vuex2增加了mapGetters和mapActions的方法,借助stage2的Object Rest Operator 所在通过 methods ...

  4. Repeater, DataList, 和GridView的区别及使用

    从对象层次图可以看出,Repeater是最轻最小的控件,它仅仅继承了基本控件的功能,包括ID属性.子控件集合等.另一方面,DataList和DataGrid则继承了WebControl功能,包括样式和 ...

  5. MybatisUtil工具类的作用

    1)在静态初始化块中加载mybatis配置文件和StudentMapper.xml文件一次 2)使用ThreadLocal对象让当前线程与SqlSession对象绑定在一起 3)获取当前线程中的Sql ...

  6. Linux添加用户/权限/用户主目录等相关

    一. 用户主目录 useradd -d   ${path}   username -d命令是指定用户主目录, 添加完之后  su -  username 默认会转到 这个用户的主目录下,即 ${pat ...

  7. 执行scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysqldb命令时一直报错:

    Can't locate Data/Dumper.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /u ...

  8. Jmeter: PATCH方法无法发送参数的暂时解决方法

    Jmeter: PATCH方法无法发送参数的暂时解决方法 最近在做API测试,前面的GET这些HTTP Request方法都无压力,顺利解决. 但碰到PATCH方法时,发现无法通过. 通过对比,发现P ...

  9. mysql 如何给大表添加字段

    1. 能不加字段就不要加, 能不修改字段就不要修改, 能不删除字段就不要删除, 等等为什么要删除字段呢? 如果没事,不要蛋疼的找事. 实际上,我们那次更新失败后, 我们并没有增加那个字段, 然后我们一 ...

  10. Linux上MongoDB一些设置

    MongoDB启动停止方法 官网安装介绍中依然有启动停止的方式 1 启动 sudo service mongod start 2 停止 sudo service mongod stop 3 重启 su ...