1.web框架
1.1web软件开发架构
cs 架构
bs 架构
bs的本质也是cs。
前端 后端(服务器)
后端实现前端以数据的交互。
2.HTTP协议
HTTP协议四大特性:
1. 基于请求响应
2. 基于tcp / ip之上的应用层协议
3. 无状态(不保存用户信息)
4. 短 / 无链接。
数据请求格式
1. 请求首行(http版本,)
2. 请求头
3. /r/n
4. 请求体
响应数据格式
1. 响应首行(状态码)
2. 响应头
3. /r/n
4. 响应体
http协议 数据传输是明文的
https协议 数据传输是密文(数据更加的安全)
3.web服务端
为send添加上HTTP协议,
请求头包含 HTTP / 1.1 HTTP的版本 200 请求状态码 \ r \ n \ r \ n 请求体
( b ' HTTP / 1.1 200 ok \ r \ n \ r \ n )
# 服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, addr = server.accept()
data = conn.recv(1024)D
print(date)
conn.send(b'HTTP/1.1 200 ok\r\n\r\nhello word')
conn.close()
date重点研究对象 ( 先省略掉 b ' GET / favicon . ico )
请求形状
b'GET / HTTP/ 1.1 \r\n
Host: 127.0 .0 .1 : 8080 \r\n
Connection: keep- alive\r\n
Cache- Control: max - age= 0 \r\n
sec- ch- ua: "Chromium" ; v= "92" , " Not A;Brand" ; v= "99" , "Microsoft Edge" ; v= "92" \r\n
sec- ch- ua- mobile: ?0 \r\n
Upgrade- Insecure- Requests: 1 \r\n
xxx
Sec- Fetch- Site: none\r\n
Sec- Fetch- Mode: navigate\r\n
Sec- Fetch- User: ?1 \r\n
Sec- Fetch- Dest: document\r\n
Accept- Encoding: gzip, deflate, br\r\n
Accept- Language: zh- CN, zh; q= 0.9 , en; q= 0.8 , en- GB; q= 0.7 , en- US; q= 0.6 \r\n\r\n'
4.依据后缀返回结果
用户输入的后缀: 127.0 .0 .1 : 8080 /index/
服务端获取的数据是二进制类型,转换为字符串类型。
GET / index / HTTP / 1.1
···
这个数据以空格进行切分,切分后是宇哥列表, / index / 的索引为 1 。
在对这个值进行判断。
import socket
server = socket. socket( )
server. bind( ( '127.0.0.1' , 8080 ) )
server. listen( 5 )
while True :
conn, addr = server. accept( )
data = conn. recv( 1024 )
data = data. decode( 'utf-8' )
res = data. split( )
print ( res[ 1 ] )
conn. send( b'HTTP/1.1 200 ok\r\n\r\n' )
if res[ 1 ] == 'index' :
conn. send( b'index' )
else :
conn. send( b'404' )
conn. close( )
4.1返回一个页面
1. 先创建一个html文件
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< title> 100G学习网址</ title>
</ head>
< body>
< a href = " https://www.baidu.com" > 进入学习</ a>
</ body>
</ html>
2. 读取文件,b模式读取为二进制,直接将html文件二进制发给浏览器,浏览器会自动进行解析并渲染。
import socket
server = socket. socket( )
server. bind( ( '127.0.0.1' , 8080 ) )
server. listen( 5 )
while True :
conn, addr = server. accept( )
data = conn. recv( 1024 )
data = data. decode( 'utf-8' )
res = data. split( )
print ( res[ 1 ] )
conn. send( b'HTTP/1.1 200 ok\r\n\r\n' )
if res[ 1 ] == 'index' :
conn. send( b'index' )
else :
conn. send( b'404' )
conn. close( )
5.wsgiref模块
wsgiref是内置模块,内置一个服务端。
from wsgiref. simple_server import make_server
def run ( env, response) :
"""
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return: 返回浏览器的数据
"""
print ( env)
response( '200 ok' , [ ] )
return [ b'hello word' ]
if __name__ == '__main__' :
server = make_server( '127.0.0.1' , 8080 , run)
server. serve_forever( )
··· 'PATH_INFO' : '/index/' ···
在依据后缀名称返回对应的值。
版本1
from wsgiref. simple_server import make_server
def run ( env, response) :
"""
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return: 返回浏览器的数据
"""
print ( env)
current_path = env. get( 'PATH_INFO' )
response( '200 ok' , [ ] )
if current_path == '/index' :
return [ b'index' ]
elif current_path == '/login' :
return [ b'index' ]
else :
return [ b'404' ]
if __name__ == '__main__' :
server = make_server( '127.0.0.1' , 8080 , run)
server. serve_forever( )
版本2
from wsgiref. simple_server import make_server
def index ( env) :
return 'index'
def login ( env) :
return 'login'
def error ( env) :
return '404'
urls= [
( '/index' , index) ,
( '/login' , login)
]
def run ( env, response) :
print ( env)
current_path = env. get( 'PATH_INFO' )
response( '200 ok' , [ ] )
func = None
for url in urls:
if current_path == url[ 0 ] :
func = url[ 1 ]
break
if func:
res = func( env)
else :
res = error( env)
return [ res. encode( 'utf-8' ) ]
if __name__ == '__main__' :
server = make_server( '127.0.0.1' , 8080 , run)
server. serve_forever( )
6.动静态网页
静态网页:页面上的数据在html网页上写死的。
动态网页:数据是实时获取的。
(
1. 后端获取时间展示到html页面。
2. 数据是从数据库中获取带html页面上。
)
将文件拆分封装。
from wsgiref. simple_server import make_server
from urls import *
def run ( env, response) :
print ( env)
current_path = env. get( 'PATH_INFO' )
response( '200 ok' , [ ] )
func = None
for url in urls:
if current_path == url[ 0 ] :
func = url[ 1 ]
break
if func:
res = func( env)
else :
res = error( env)
return [ res. encode( 'utf-8' ) ]
if __name__ == '__main__' :
server = make_server( '127.0.0.1' , 8080 , run)
server. serve_forever( )
from views import *
urls = [
( '/index' , index) ,
( '/login' , login) ,
( '/study' , study) ,
( '/get_time' , get_time)
]
def index ( env) :
return 'index'
def login ( env) :
return 'login'
def error ( env) :
return '404'
def study ( env) :
with open ( 'templates/myhtml.html' , mode= 'rt' , encoding= 'utf-8' ) as f:
return f. read( )
import datetime
def get_time ( env) :
current_time = datetime. datetime. now( ) . strftime( '%Y-%m-%d %H:%M:%S' )
with open ( 'templates/my_time.html' , mode= 'rt' , encoding= 'utf-8' ) as f:
date = f. read( )
date = date. replace( 'xxx' , current_time)
return date
templates 文件夹
将所有的网页都村在这个文佳夹。
# myhtml.html templates 文件夹下
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< title> 100G学习网址</ title>
</ head>
< body>
< a href = " https://www.baidu.com" > 进入学习</ a>
</ body>
</ html>
# get_time.html templates 文件夹下 动态网页
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< title> time</ title>
</ head>
< body>
xxx
</ body>
</ html>
借助于wsgiref模块 函数对应关系
views . ps 视图函数(后端业务逻辑)
templates文件夹 专门存储html文件
安装功能的不同拆分之后后续添加功能只需要在urls . py书写对应的关系然后取
views . py的书写业务逻辑。
7.模板
将一个字典传递给html文件,并可以在文件时上便捷的操作字典数据。
( '/get_dict' , get_dict)
在templates文佳下创建get_dir . html文件
模板语法是在后端起作用的
-------------------------------------
< ! DOCTYPE html >
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< title > Title < / title >
< / head >
< body >
< h1 > 我是一个页面 < / h1 >
< ! -- 模板语法 -- >
{ { user } }
{ { user . get ( 'username' ) } }
{ { user . age } }
{ { user [ 'hobby' ] } }
< / body >
< / html >
from jinja2 import Template
def get_dict ( env) :
user_div = { 'username' : 'kid' , 'age' : 18 , 'hobby' : 'read' }
with open ( 'templates/get_dic.html' , mode= 'rt' , encoding= 'utf-8' ) as f:
data = f. read( )
tmp = Template( data)
res = tmp. render( user= user_div)
return res
8.简易版本web框架流程
wsgiref模块
1. 请求来的时候解析http格式的数据 封装成大字典
2. 响应走的时候给数据打包成符合http格式 再返回给浏览器
9.三大主流框架
django
特点 : 大而全 自带的功能特别特别特别的多 类似于航空母舰
不足之处 :
有时候过于笨重
flask
特点 : 小而精 自带的功能特别特别特别的少 类似于游骑兵
第三方的模块特别特别特别的多,如果将flask第三方的模块加起来完全可以盖过django
并且也越来越像django
不足之处 :
比较依赖于第三方的开发者
tornado
特点 : 异步非阻塞 支持高并发
牛逼到甚至可以开发游戏服务器
不足之处 :
暂时你不会
10.注意事项
正常启动Django项目需要注意事项:
1. 计算机的名称不能有中文
2. 一个Python窗口中只能有一个项目
3. 项目里所有的文件不要使用中文
4. Python解释器尽量使用 3.4 - 3.6 之间的版本
如果项目报错。点最后一个报错信息,去源码中把逗号删除。
版本问题:
1 x ( 1.11 版本为例 )
2 x
3 x ( 还在开发完善中 )
1. x于 2. x差别不大。
安装
pip3 install django = = 1.11 .11
验证是否安装成功
1. 安装后会自动添加到环境变量中,在任何终端位置输入 django-admin 查看反应
11.django基本操作
11.1命令行操作
1.创建项目
先切换目录再代打开终端,在某个目录按下cmd就会在当前目录打开终端。
django-admin startproject mysite
生成
mysize文件夹
mysize文件下
__init__ . py
settings . py
urls . py
wsgi . ps
2.启动项目
在启动时一定要切换到目录mysize文件夹下
python manage . py runserver
Starting development server at http : / / 127.0 .0 .1 : 8000 /
在浏览器输入 127.0 .0 .1 : 8000 验证
It worked !
Congratulations on your first Django-powered page .
Next , start your first app by running . python manage . py startapp [ app_label ]
You 're seeing this message because you have in your Django settings file and you haven' t configured any URLs . Get to work ! DEBUG = True
成功了!
祝贺您的第一个 Django 供电页面。
接下来,通过运行启动您的第一个应用程序。python manage . py startapp [ app_label ]
您看到此消息是因为您在 Django 设置文件中拥有该消息,并且尚未配置任何 URL。去上班吧!DEBUG = True
3.创建应用
创建的引用一定需要去配置文件中注册才能使用。
django框架一款专门开发app的web框架。app : 计算机的 应用程序 ;
django是一个空架子需要自己开发对应的app。
应用名因该见名知意
python manage . py startapp app01
生成一个app01的文件夹
11.2Pycharm创建
1.创建项目
1. 新建项目 -- > Django -- > python 3.6
2. 设置more settings -- > 勾选 Enable Django admin
3. 点击create
2.启动项目
启动:
1. 命令行启动
2. 启动按键启动
3.创建应用
创建的引用一定需要去配置文件中注册才能使用。
使用Pytharm创建项目的时候,只可以创建一个app并自动注册。
创建应用:
1. Python的终端中命令行创建 python manage . py startapp app01
2. Python Tools - > run manage . py task 会这些这个程序,终端输入就提供了代码补全提示。
执行出错或在在查看项目Django时候报错:
TypeError : unsupported operand type ( s ) for / : ‘str’ and ‘str’,
这是由于自动生成的代码中存在语法错误,点击最后一行报错信息,跳转到该行,
(在settings . py中的错误代码为 'DIRS' : [ BASE_DIR / 'templates' ] ),
将其修改为 'DIRS' : [ str . format ( BASE_DIR , '/templates' ) ] 。
再次运行则不会在报错。
4.修改端口号
12.命令与Pytharm创建的区别
Python创建会自动创建一个templates文件夹,存放html文件,
并将它的路劲添加到配置文件中。
而命令行创建不会创建templatew文件夹。
# pycharm创建
TEMPLATES = [
{
'BACKEND' : 'django.template.backends.django.DjangoTemplates' ,
'DIRS' : [ os . path . join ( BASE_DIR , 'templates' ) ]
]
# 命令行创建
TEMPLATES = [
{
'BACKEND' : 'django.template.backends.django.DjangoTemplates' ,
'DIRS' : [ ] ,
]
"" "
命令行创建templatew文件夹自己添加路径:
'DIRS' : [ os . path . join ( BASE_DIR , 'templates' ) ]
"" "
13.主要文件介绍
mysite项目文件夹
mysite文佳夹
settings . py 配置文件
urls . py 路由于视图h函数对应关系(路由层)
wsgi . ps wsgiref模块
manage . py gjango 入口文件
db . sqliste3 gjango自带的sqliste3数据库
templates 文件夹 存放html文件
app01 文佳夹
admin . py django后台管理
apps . py 注册使用
migrations 文件夹 数据迁移记录
models . ps 数据库相关的 模型类(orm)
tests . py 测试文件
views . py 视图函数(视图层)
14文件代码介绍
1.settings配置文件
import os
BASE_DIR = os. path. dirname( os. path. dirname( os. path. abspath( __file__) ) )
SECRET_KEY = 'opirx+^uj&0%gv279+n)l6%-1)1l8osqj4oshkg0-ln@yuq26i'
DEBUG = True
ALLOWED_HOSTS = [ ]
INSTALLED_APPS = [
'django.contrib.admin' ,
'django.contrib.auth' ,
'django.contrib.contenttypes' ,
'django.contrib.sessions' ,
'django.contrib.messages' ,
'django.contrib.staticfiles' ,
]
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' ,
]
ROOT_URLCONF = 'djangoProject.urls'
TEMPLATES = [
{
'BACKEND' : 'django.template.backends.django.DjangoTemplates' ,
'DIRS' : [ str . format ( BASE_DIR, '/templates' ) ]
,
'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' ,
] ,
} ,
} ,
]
WSGI_APPLICATION = 'djangoProject.wsgi.application'
DATABASES = {
'default' : {
'ENGINE' : 'django.db.backends.sqlite3' ,
'NAME' : os. path. join( BASE_DIR, 'db.sqlite3' ) ,
}
}
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
15 django三板斧
1. 先创建一个项目
2. 建立app python manage . py startapp app01
# Django在修改文件时会直接作用到到程序。程序可以不必重新启动。
from app01 import views
urlpatterns = [
url( r'^admin/' , admin. site. urls) ,
url( r'index1/' , views. index1) ,
url( r'index2/' , views. index2) ,
url( r'index3/' , views. index3) ,
]
from django. shortcuts import render, HttpResponse, redirect
def index1 ( request) :
"""
:param request: 请求相关的所有数据对象。
:return:
"""
return HttpResponse( 'XXXX' )
1.HttpResponse
HttpResponse 返回字符串类型数据
def index1 ( request) :
return HttpResponse( 'XXXX' )
浏览器 127.0 .0 .1 /index/
显示XXXX
2.render
render 返回html文件
# 在创建项目的时候创建了templas文件夹并自动添加了环境变量,
在写参数时写文件名旧可以了,会自动查找。
# templates文佳夹下创建一个html文件
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< title> 练习</ title>
</ head>
< body>
< a href = " http://www.baidu.com" > 百度</ a>
</ body>
</ html>
def index2 ( request ) :
return render ( request , '01.html' )
3.redirect
redirect 重定向
即可以打开别人的网址也可以打开自己的网址。
def index3 ( request) :
return redirect( 'https://www.baidu.com' )
def index3 ( request) :
return redirect( '/index1/' )
1.HttpResponse
HttpResponse 返回字符串类型数据
def index1 ( request) :
return HttpResponse( 'XXXX' )
浏览器 127.0 .0 .1 /index/
显示XXXX
2.render
render 返回html文件
# 在创建项目的时候创建了templas文件夹并自动添加了环境变量,
在写参数时写文件名旧可以了,会自动查找。
# templates文佳夹下创建一个html文件
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< title> 练习</ title>
</ head>
< body>
< a href = " http://www.baidu.com" > 百度</ a>
</ body>
</ html>
def index2 ( request ) :
return render ( request , '01.html' )
3.redirect
redirect 重定向
即可以打开别人的网址也可以打开自己的网址。
def index3 ( request) :
return redirect( 'https://www.baidu.com' )
def index3 ( request) :
return redirect( '/index1/' )