目录

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. Android中代码优化

    两个基本准则: 1.不要做冗余的工作 2.尽量避免次数过多的内存分配操作 Handler和内部类的正确使用 正确使用Context 正确使用Java四种引用方式:软引用,弱引用,虚引用,强引用 避免创 ...

  2. Grafana添加Zabbix为数据源(一)

    最前面,此博文引自:http://docs.grafana-zabbix.org/installation/configuration-sql/ 使用zabbix来收集书籍,用grafana来显示数据 ...

  3. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_4-1.单机和分布式应用的登录检验讲解

    笔记 第四章 开发在线教育视频站点核心业务之JWT微服务下的用户登录权限校验 1.单机和分布式应用的登录检验讲解     简介:讲解单机和分布式应用下登录校验,session共享,分布式缓存使用 1. ...

  4. CentOS7+rsync+sersync实现数据实时同步

    一.全网数据备份方案 1.需要备份的文件目录有(原则上,只要运维人员写入或更改的数据都需要备份)./data,/etc/rc.local,/var/spool/cron/root等,根据不同都服务器做 ...

  5. Spark算子与RDD基本转换

    map 将一个RDD中的每个数据项,通过map中的函数映射变为一个新的元素. 输入分区与输出分区一对一,即:有多少个输入分区,就有多少个输出分区. flatMap 属于Transformation算子 ...

  6. Tanimoto Coefficient

    Tanimoto Coefficient The Tanimoto coefficient between two points, a and b, with k dimensions is calc ...

  7. Linux学习笔记:shell

    目录 通配符 特殊符号 变量 环境变量 默认变量 shell script case if for until while function 本文更新于2019-08-23. 通配符 *:0个至无穷多 ...

  8. django 之(三) --- 会话|关系|静态*

    会话技术 HTTP在web开发中基本都是短连接[一个请求的生命周期都是从request开始到response结束]. 下次再来请求就是一个新的连接了.为了让服务器端记住用户端是否登陆过就出现了会话技术 ...

  9. JS动态添加的标签无法绑定事件解决方案~~~

    今天用ajax实现动态插入数据时发现监听一直不起作用,一样的代码,非动态的就可以监听实现 这是困扰了我近一个小时的bug,后面才理解到可能是动态插入导致的! 看了看网上的解决方案,似乎都不太通俗,讲的 ...

  10. Django 框架学习 ---- 安装

    这里引用了源码方式安装: 1.git clone https://github.com/django/django.git 2.cd django/ 3.python setup.py install ...