手写的简易web框架
import socket server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) """ 请求首行 b'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 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36 Sec-Fetch-User: ?1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: csrftoken=aOZSalMQkKGbzstfjcw3O9sDoegdywL8AD7PzhidAyx3tXShN7oQtxN1MMnS6GVX (******) 请求体 ' """ while True: conn, addr = server.accept() # 阻塞态 data = conn.recv(1024) # print(data) conn.send(b'HTTP/1.1 200 OK ') data_str = data.decode('utf-8') current_path = data_str.split(' ')[0].split(' ')[1] # print(current_path) if current_path == '/index': # conn.send(b'index') with open(r'01 纯手撸的前端页面.html','rb') as f: conn.send(f.read()) elif current_path == '/login': conn.send(b'login') else: conn.send(b'404 error') conn.close()
基于wsgiref模块些web框架
基于第三方模块帮你撸
views.py 里面的放的是函数 我们管这些函数叫视图函数 视图层
urls.py 里面放的是 路由(后缀)与视图函数的对应关系 路由层
templates文件夹 里面放的全是html文件
from wsgiref.simple_server import make_server from urls import urls from views import * def run(env,response): """ :param env: 请求相关的所有数据 将http数据全部提前处理成了字典的形式 供调用者使用 :param response: 响应相关的所有数据 :return: 给前端真正的数据 """ # print(env) response('200 OK',[('xxx','jason'),]) current_path = env.get('PATH_INFO') # print(current_path) # if current_path == '/index': # return [b'index'] # elif current_path == '/login': # return [b'login'] # 定义一个存储函数名的标志位 func = None for url in urls: # url = ('/login',login) ('/index',index) if current_path == url[0]: # 用户敲的后缀名 你后端有对应的处理业务 func = url[1] # 将匹配上的函数名赋值给func变量 break # 一旦用户匹配上了对应的业务接口 立刻结束匹配 # 判断func是否被赋值 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) # 实时监听本机8080端口 # 一旦有请求来了 会统一交给run函数处理(调用run函数并传参run(env,response)) server.serve_forever() # 启动服务端
动静态网页
静态网页
数据是写死的 万年不变(哪怕改变了 也是人为直接修改)
动态网页
数据是实时获取的
eg:
1 后端代码动态获取 当前时间
2 数据是从数据库查询出来的
例:访问页面 页面上展示当前访问的时间
import time def get_time(env): ctime = time.strftime('%Y-%m-%d %X') # 后端数据 如何传递给html页面(利用字符串的替换) with open(r'templates/03 get_time.html','r',encoding='utf-8') as f: data = f.read() data = data.replace('sadadadasdsadsad',ctime) return data
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css"> <script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> </head> <body> sadadadasdsadsad </body> </html>
例:访问页面 页面上展示后端用户字典 并且在前端页面上可以
利用一些简便的方式操作字典取值
from jinja2 import Template def get_userdict(env): user_dic = {'username':'jason','age':18,'hobby':['read','book','run']} with open(r'templates/04 get_user.html','r',encoding='utf-8') as f: data = f.read() temp = Template(data) res = temp.render(userDic = user_dic) # 将user_dic传递给html页面 页面上通过userDic就能够拿到后端传递过来的值 return res
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css"> <script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> </head> <body> <p>{{ userDic }}</p> <p>{{ userDic.username }}</p> <p>{{ userDic['age'] }}</p> <p>{{ userDic.get('hobby') }}</p> <p>{{ userDic.get('hobby').0 }}</p> <p>{{ userDic.get('hobby').1 }}</p> <p>{{ userDic.get('hobby').2 }}</p> </body> </html>
jinja2模板语法
专门用来处理后端数据与html页面的交互
模板语法(极其贴近python后端语法)
让你能够在html页面上 也能够用后端python语法来操作后端传递过来的数据
<p>{{ userDic }}</p>
<p>{{ userDic.username }}</p>
<p>{{ userDic['age'] }}</p>
<p>{{ userDic.get('hobby') }}</p>
<p>{{ userDic.get('hobby').0 }}</p>
<p>{{ userDic.get('hobby').1 }}</p>
<p>{{ userDic.get('hobby').2 }}</p>
{% for user_dic in user_list %}
<tr>
<td>{{ user_dic.id }}</td>
<td>{{ user_dic.username }}</td>
<td>{{ user_dic.password }}</td>
</tr>
{% endfor %}
模板的渲染 将后端传递给html文件的数据 在后端处理好 生成一个完整的html文件的过程
注意 模板的渲染是在后端完成的 跟前端没有关系
数据库的交互
import pymysql def get_data(env): conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123qwe', db = 'day49', charset = 'utf8', autocommit = True ) cursor = conn.cursor(pymysql.cursors.DictCursor) # 将查出来的数据组织成一个字典 sql = "select * from userinfo" # 关键性的数据 不要自己手动拼接 affect_rows = cursor.execute(sql) # sql注入:就是利用MySQL注释语法 # print(affect_rows) user_list = cursor.fetchall() # print(user_list) # return 'hahahahha' with open(r'templates/05 get_data.html','r',encoding='utf-8') as f: data = f.read() temp = Template(data) res = temp.render(user_list = user_list) return res
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h2 class="text-center">数据展示</h2> <table class="table table-striped table-bordered table-hover"> <thead> <tr> <th>id</th> <th>username</th> <th>password</th> </tr> </thead> <tbody> {% for user_dic in user_list %} <tr> <td>{{ user_dic.id }}</td> <td>{{ user_dic.username }}</td> <td>{{ user_dic.password }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html>
python三大主流web框架(了解知识)
django 大而全 自带的组件和功能非常非常多 类似于航空母舰
不足之处:写小项目的时候 可能会比较笨重(大材小用)
flask 小而精 短小精悍 自带的组件和功能特别特别少 类似于游骑兵
基本全部依赖于第三方组件
不足之处:受限于第三方模块的影响比较大
如果将flask所有第三方模块加起来 能够直接盖过django
tornado 异步非阻塞 这个框架甚至可以用来开发游戏服务器
a:socket部分
b:路由匹配
c:模板语法
django:
a用的别人的wsgiref(django默认的)
b自己写的
c自己写的
flask:
a用的别人的werkzeug
b自己写的
c用的别人的jinja2
Tornado:
a,b,c都是自己写的
django框架介绍
注意事项
1.计算机名称不能有中文
2.python解释器不要使用3.7版本 推荐使用版本3.4~3.6
3.一个pycharm窗口 只能跑一个项目
Django框架的安装与使用
django版本问题
django版本以1.11.11为主(1.11.9~1.11.13)
如果安装网络不稳定,可以修改下载的源:
如何检验django是否安装成功
命令行敲 django-admin
命令行创建项目
1.创建django项目
django-admin startproject 项目名(例如mysite)
2.启动django项目
切换到项目文件夹下
python3 manage.py runserver
或:python3 manage.py runserver 127.0.0.1:8080
3.创建应用(django支持多app开发)
python manage.py startapp app01
命令行创建注意
1.不会自动帮你创建templates文件夹
2.配置文件中不会自动帮你书写templates文件路径
要在配置文件的TEMPLATES 中手动添加'DIRS': [os.path.join(BASE_DIR, 'templates')]
app的概念
django是一个以开发app为主要功能的web框架
app就是application应用的意思
一个django项目就是一所大学(空的架子 本身没有任何功能)
而app就类似于大学里面的各个学院
一个空的django本身没有任何作用 仅仅是为app提供前期的环境配置
你可以根据功能的不同 开发多个app
一个app对应一个具体的功能模块
用户相关的功能 用户相关的app
订单相关的功能 订单相关的app
商品相关的功能 商品相关的app
每一个app都有自己独立的功能
******************************注意***************************
创建好的app需要在django配置文件中注册方可生效
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 'app01' # 简便写法
'app01.apps.App01Config' # 最完整的写法
]
设置端口:
1.创建应用的时候 可以使用简便方式
在命令行创建app:
python manage.py startapp app01
或者:
Tools >>> run manage.py task
2.一定要确保同一个端口 同一时间只能启一个django项目
3.配置文件中针对templates文件夹的路径 如果是空的需要你手动配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(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',
],
},
},
]
django文件功能
django项目名
项目同名的文件夹
settings.py 暴露给用户可以配置的配置文件
urls.py 路由与视图函数对应关系
manage.py django的入口文件
应用名文件夹
migrations文件夹 所有数据库相关的操作记录
admin.py django admin后台管理
apps.py 注册app使用
models.py 放所有数据库相关的模型类
tests.py 测试文件
views.py 处理业务逻辑的视图函数
django基本配置及注意事项
django小白必会三板斧
HttpResponse 返回字符串
render 返回html文件
redirect 重定向
HttpResponse 返回字符串
render 返回html文件
可以给html页面传值
def login(request):
user_dic = {'username':'jason','password':'123'}
return render(request,'login.html',{'xxx':user_dic})
redirect 重定向
1.直接写你本网站的路径后缀
2.也可以全路径
def home(request):
# return redirect('/login') # 重定向
return redirect('https://www.baidu.com') # 重定向
注意
django默认是自动重启的
重启机制
内有检测机制 实时检测所有文件的变化
有时候会产生 你代码还没写完 就自动重启报错的情况 不用管
每次写完代码之后 自己手动重启