python django基础一web框架的本质

web框架的本质就是一个socket服务端,而浏览器就是一个socker客户端,基于请求做出相应,客户端先请求,服务器做出对应响应

按照http协议的请求发送,服务器按照http协议来相应,这样的通信就可以自己实现web框架了

简单web框架

import socket

server = socket.socket()
server.bind(('127.0.0.1', 8080)) # 把地址绑到套接字
server.listen() # 监听链接
while 1:
conn, addr = server.accept() # 接受客户端连接
from_b_msg = conn.recv(1024).decode('utf-8') # 接收客户端信息
print(from_b_msg)
path = from_b_msg.split('\r\n')[0].split()[1] # 赛选到客户端的第一行信息 conn.send(b'HTTP/1.1 200 ok\r\n\r\n')
# http响应格式 1.状态行 回车符 换行符 2.相应头部头部字段:值 回车符 换行符 回车符 换行符响应正文 # conn.send(b'hello')
if path == '/':
# 只写这一个 你会发现 该 网页css js 应用都没应用上 因为他们 请求/test.css /timg.jpg
with open('test.html', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
elif path == '/test.css':
with open('test.css', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
elif path == '/timg.jpg':
with open('timg.jpg', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
elif path == '/test.js':
with open('test.js', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()
elif path == '/meinv.ico':
with open('meinv.ico', 'rb') as f:
data = f.read()
conn.send(data)
conn.close()

test.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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<link rel="stylesheet" href="test.css">
<link rel="icon" href="meinv.ico"> <!-- Bootstrap -->
<!--<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">--> <style> </style>
</head>
<body> <h1>来首诗,菩提本无树,明镜亦非台</h1> <!--<img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1550637152712&di=1caeff14731881d6d2ad4d9681ad031a&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F0b55b319ebc4b7454d716709c5fc1e178b8215c3.jpg" alt="">-->
<img src="timg.jpg" alt=""> <!--<script src="jquery.js"></script>-->
<!--<script src="bootstrap/js/bootstrap.min.js"></script>-->
<!--<script>--> <!--alert('xxx');--> <!--</script>-->
<script src="test.js"></script> </body>
</html>

test.css

h1{
background-color: green;
}
img{
width: 200px;
height: 200px;
}

test.js

alert('xxx');
这2个图片 我就不提供了

timg.jpg
meinv.ico

超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)

HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。

工作原理

1.客户端到连接服务器

一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接:如http://www.baidu.com

2.发送http请求

通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。

python django基础一web框架的本质

URL包含:/index/index2?a=1&b=2;路径和参数都在这里。

python django基础一web框架的本质

3.服务接收请求并返回http响应

Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。

python django基础一web框架的本质

python django基础一web框架的本质

 4.释放连接tcp连接

若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;

 

5.客户端浏览器解析HTML内容

客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

只加根判断应答会出现 下面情况

python django基础一web框架的本质

请求方式: get与post请求(通过form表单我们自己写写看)

  • GET提交的数据会放在URL之后,也就是请求行里面,以?分割URL和传输数据,参数之间以&相连,如EditBook?name=test1&id=123456.(请求头里面那个content-type做的这种参数形式,后面讲) POST方法是把提交的数据放在HTTP包的请求体中.
  • GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
  • GET与POST请求在服务端获取请求数据方式不同,就是我们自己在服务端取请求数据的时候的方式不同了,这句废话昂。

http状态码

  • 1xx消息——请求已被服务器接收,继续处理
  • 2xx成功——请求已成功被服务器接收、理解、并接受
  • 3xx重定向——需要后续操作才能完成这一请求
  • 4xx请求错误——请求含有词法错误或者无法被执行
  • 5xx服务器错误——服务器在处理某个正确请求时发生错误

高级点的 web框架

from threading import Thread
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen() def html(conn):
with open('test.html', 'rb') as f:
data = f.read()
conn.send(data)
conn.close() def js(conn):
with open('test.js', 'rb') as f:
data = f.read() conn.send(data)
conn.close() def css(conn):
with open('test.css', 'rb') as f:
data = f.read() conn.send(data)
conn.close() def img(conn):
with open('timg.jpg', 'rb') as f:
data = f.read() conn.send(data)
conn.close() def ico(conn):
with open('meinv.ico', 'rb') as f:
data = f.read()
conn.send(data)
conn.close() url = [
('/', html),
('/test.css', css),
('/timg.jpg', img),
('/test.js', js),
('/meinv.ico', ico),
] while 1:
conn, addr = server.accept()
from_b_msg = conn.recv(1024).decode('utf-8') path = from_b_msg.split('\r\n')[0].split(' ')[1]
conn.send(b'HTTP/1.1 200 ok\r\nk1:v1\r\n\r\n')
for i in url:
if i[0] == path:
t=Thread(target=i[1],args=(conn,))
t.start()

根据不同路径返回不同页面 web框架  返回动态页面web框架

from threading import Thread
import socket
server = socket.socket()
# server.bind(('192.168.12.45',8080))
server.bind(('127.0.0.1',8080))
server.listen() import datetime
def base(conn):
with open('base.html','r',encoding='utf-8') as f:
data = f.read()
t1 = datetime.datetime.now()
new_data = data.replace('@xx@',str(t1))
conn.send(new_data.encode('utf-8')) #conn是形参 是发送消息conn 管道
def index(conn):
with open('index.html', 'rb') as f:
data = f.read()
conn.send(data) def home(conn):
with open('home.html', 'rb') as f:
data = f.read()
conn.send(data) def articles(conn):
with open('art.html', 'rb') as f:
data = f.read()
conn.send(data) urlpatterns=[
('/',base),
('/index',index),
('/home',home),
('/articles',articles), ] while 1:
conn, addr = server.accept()
from_b_msg = conn.recv(1024).decode('utf-8')
print(from_b_msg) path = from_b_msg.split('\r\n')[0].split(' ')[1]
# print(path)
conn.send(b'HTTP/1.1 200 ok\r\nk1:v1\r\n\r\n')
# conn.send(b'<h1>hello</h1>')
for url_func in urlpatterns:
if url_func[0] == path:
#多线程函数版
#注意这传参是实参
t = Thread(target=url_func[1],args=(conn,))
t.start()
# 简单函数版
# url_func[1](conn)

base.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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title> <!-- Bootstrap -->
<!--<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">--> </head>
<body> <h1 style="color: purple;">欢迎来到王者荣耀页面</h1> <a href="http://127.0.0.1:8080/index">这是index</a>
<a href="http://127.0.0.1:8080/home">这是home</a> <h1 style="color: pink;">@xx@</h1>
<!--<script src="jquery.js"></script>-->
<!--<script src="bootstrap/js/bootstrap.min.js"></script>--> </body>
</html>

index.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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title> <!-- Bootstrap -->
<!--<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">--> </head>
<body> <div>这是index页面</div> <!--<script src="jquery.js"></script>-->
<!--<script src="bootstrap/js/bootstrap.min.js"></script>--> </body>
</html>

home.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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title> <!-- Bootstrap -->
<!--<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">-->
</head>
<body> <h1>这是home页面</h1> <!--<script src="jquery.js"></script>-->
<!--<script src="bootstrap/js/bootstrap.min.js"></script>--> </body>
</html>

form表单提交

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8080" method="">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit"></input>
</form>
</body>
</html>

server 得到数据

GET /?username=zaizai&password=123 HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36

爬虫模拟user-agent

import requests

# res = requests.get('https://www.jd.com')
res = requests.get('https://dig.chouti.com/',headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36', }) # print(res.text) with open('ct.html','w',encoding='utf-8') as f:
f.write(res.text)

wsgire模块

from wsgiref.simple_server import make_server
# wsgiref本身就是个web框架,提供了一些固定的功能(请求和响应信息的封装,不需要我们自己写原生的socket了也不需要咱们自己来完成请求信息的提取了,提取起来很方便)
#函数名字随便起
def application(environ, start_response):
'''
:param environ: 是全部加工好的请求信息,加工成了一个字典,通过字典取值的方式就能拿到很多你想要拿到的信息
:param start_response: 帮你封装响应信息的(响应行和响应头),注意下面的参数
:return:
'''
start_response('200 OK', [('Content-Type', 'text/html'),('k1','v1')])
# print(environ)
print('>>>>>',environ['PATH_INFO']) #输入地址127.0.0.1:8000,这个打印的是'/',输入的是127.0.0.1:8000/index,打印结果是'/index'
return [b'<h1>Hello, web!</h1>'] #和咱们学的socketserver那个模块很像啊
httpd = make_server('127.0.0.1', 8080, application) print('Serving HTTP on port 8080...')
# 开始监听HTTP请求:
httpd.serve_forever()

基于wsgire模块 起飞版框架

先看一下分析图

python django基础一web框架的本质

manage.py

from urls import url_patterns
from wsgiref.simple_server import make_server # 框架主逻辑代码
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html'), ('k1', 'v1')]) path = environ['PATH_INFO'] # 所有的请求 取到其中的
print('path>>>', path)
data = b'page not found ,404!!!'#没有走404
for path_func in url_patterns:
if path == path_func[0]:
data = path_func[1](environ)
print(data)
return [data] httpd = make_server('127.0.0.1', 8080, application) print('Serving HTTP on port 8080...') httpd.serve_forever()

ruls文件

import views

# 路径与函数的对应关系
url_patterns = [
('/', views.base),
('/login',views.login),
('/auth',views.auth) ]

views文件

import pymysql
from urllib.parse import parse_qs # 首页处理函数
def base(environ):
with open('templates/base.html', 'rb') as f:
data = f.read()
return data def login(environ):
with open('templates/login.html', 'rb') as f:
data = f.read()
return data user = None def auth(environ):
args = parse_qs(environ['QUERY_STRING']) # 可把用户请求转化成字典
username = args['username'][0]
password = args['password'][0]
# print('>>>>>',parse_qs(args)) #{'a': ['1'], 'b': ['2']}
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123456.com',
database='auth',
charset='utf8'
)
cursor = conn.cursor()
sql = 'select * from userinfo where name=%s and password=%s;'
res = cursor.execute(sql, [username, password])
if res:
global user
user = username
with open('templates/base.html', 'rb') as f:
data = f.read()
else:
data = '密码错误'.encode('gbk')
return data

models文件

# 通过pymysql来创建表

import pymysql

conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123456.com',
database='auth',
charset='utf8' ) cursor = conn.cursor(pymysql.cursors.DictCursor) sql = """
# create table userinfo(
# id int primary key auto_increment,
# name char(20) not null unique,
# password char(20) not null
#
# ); insert into userinfo(name,password) values('alex','123'),('alexsb','123'); """ cursor.execute(sql) conn.commit() conn.close()

templates文件夹 下面存放html文件

base.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>欢迎</h1> </body>
</html>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8080/auth">
<label for="username">用户名</label>
<input type="text" id="username" name="username">
<label for="password">密码</label>
<input id="password" type="password" name="password">
<input type="submit">
</form> </body>
</html>

MVT和MTV的差别

  将来要说的MVC框架是什么呢:

    M:model.py  就是和数据库打交道用的,创建表等操作

    V:View  视图(视图函数,html文件)

    C:controller  控制器(其实就是我百度云代码里面那个urls文件里面的内容,url(路径)分发与视图函数的逻辑处理)

  Django叫做MTV框架

    M:model.py  就是和数据库打交道用的,创建表等操作(和上面一样)

    T:templates  存放HTML文件的

    V:View 视图函数(逻辑处理)

    其实你会发现MTV比MVC少一个url分发的部分

    所以我们学的django还要学一个叫做url控制器(路径分发)的东西,MTV+url控制器就是我们django要学的内容。  

模版渲染jinja2

实现了一个简单的动态页面(字符串替换)

import socket
from threading import Thread
from jinja2 import Template
import datetime server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen() def base(conn):
# with open('base.html','r',encoding='utf-8') as f:
# data = f.read()
# t1 = datetime.datetime.now()
# new_data = data.replace('@xx@',str(t1))
# conn.send(new_data.encode('utf-8'))
with open('jinja2page.html', 'r', encoding='utf-8') as f:
data = f.read() t = Template(data) new_data = t.render({"name": "于谦", "hobby_list": ["烫头", "泡吧"]})
# return
conn.send(new_data.encode('utf-8')) urlpatterns = [
('/', base), ] while 1:
conn, addr = server.accept()
from_b_msg = conn.recv(1024).decode('utf-8')
path = from_b_msg.split('\r\n')[0].split(' ')[1]
# print(path)
conn.send(b'HTTP/1.1 200 ok\r\nk1:v1\r\n\r\n')
# conn.send(b'<h1>hello</h1>')
for url_func in urlpatterns:
if url_func[0] == path:
# 多线程函数版
t = Thread(target=url_func[1], args=(conn,))
t.start()
# 简单函数版
# url_func[1](conn)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>姓名:{{name}}</h1> <ul>
{% for hobby in hobby_list %}
<li>{{hobby}}</li>
{% endfor%}
</ul>
</body>
</html>

Django下载安装

pip3 install django==1.11.9

django-admin startproject mysite   创建了一个名为"mysite"的Django 项目:

python manage.py runserver 127.0.0.1:8080  #此时已经可以启动django项目

django-admin startapp app02 或者使用python manage.py startapp blog   #通过执行manage.py文件来创建应用

python manage.py runserver 8080   #本机就不用写ip地址了 如果连端口都没写,默认是本机的8000端口

http://127.0.0.1:8080/时就可以看到

pycharm 创建方法

python django基础一web框架的本质

python django基础一web框架的本质

python django基础一web框架的本质

django 简单使用方法

目录结构

mysite 目录结构
manage.py
mysqite
settings.py 项目全局的配置信息
urls.py 路径和函数对应关系
wsgi.py socket相关的
app01
views.py 视图函数 就是业务逻辑代码
models.py 数剧库相关
templates 存放html文件的
django settings 配置文件里面关于这个文件夹的配置
'DIRS':[os.path.join(BASE_DIR,'templates')]

urls改变如下

from blog import views #引入views

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^login/', views.login),
url(r'^home/', views.home)
]

tempalates 下添加需要的html

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ t }}</h1>
</body>
</html>

login.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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title> </head>
<body> <form action="http://127.0.0.1:8000/login/" method="get">
<label for="username">用户名</label><input id="username" type="text" name="username">
<label for="password">密码</label><input id="password" type="password" name="password">
<input type="submit">
</form> </body>
</html>

在应用app下 添加需要的应用信息

from django.shortcuts import render,HttpResponse
import datetime # Create your views here. def index(request):
newdata = str(datetime.datetime.now())
return render(request, 'index.html', {'t': newdata})
def home(request):
return render(request,'login.html') def login(request): #获取用户的请求方法
method = request.method
if method == 'GET':
# #返回页面
# return render(request,'login.html')
#
# else:
#post方法获取数据,都是字符串类型
# uname = request.POST.get('username')
#get方法获取数据,都是字符串类型 uname = request.GET.get('username')
pwd = request.GET.get('password')
print(uname,pwd) #alex 123 if uname == 'sb' and pwd == '':
#返回消息,写字符串就行
return HttpResponse('登录成功') else:
return HttpResponse('验证失败')

进行登陆验证

python django基础一web框架的本质

失败后 会返回登陆失败   成功后返回成功

index 是一个动态的jianjia2 相应页面

python django基础一web框架的本质

上一篇:标识映射(Identify Map)


下一篇:SRM 511 DIV1 500pt(DP)