Python入门自学进阶-Web框架——42、Web框架了解-bottle、flask

WEB框架的三大组件:路由系统、控制器(含模板渲染)、数据库操作

微型框架:依赖第三方写的socket,WSGI,  本身功能少

安装:
pip install bottle


pip install flask

安装flask,同时安装了MarkupSafe、Werkzeug、Jinja2、itsdangerous。
Werkzeug是Python的WSGI规范的实用函数库。使用广泛,基于BSD协议,是Flask使用的底层WSGI库;
itsdangerous是flask中引用的一个第三方包,用来解决生成token等网络安全问题;
MarkupSafe为 Python 实现 XML/HTML/XHTML 标记安全字符串;
Jinja2是一个模板语言,是一个现代的、设计友好的、依照django模板的python模板语言;

pip install tornado

已经安装过。

Bottle:

一个程序文件完成整个网站:

from bottle import template,Bottle
root = Bottle()@root.route('/hello/')  
# 装饰器,定义了URL,即/hello/这个url由index这个函数来处理,就是路由系统
def index():return "Hello World!"root.run(host='localhost', port=8080)
# 这里就是启动webserver服务器,然后等待请求

运行整个Python程序:

浏览器端请求:

上面的路由(即装饰器)是静态路由,还可以使用动态路由:

@root.route('/wiki/<pagename>')
def
 callback(pagename):
    ...

pagename作为参数变量名,匹配字符串。

@root.route('/object/<id:int>')
def
 callback(id):
    ...
id是一个int型的参数变量名。

@root.route('/show/<name:re:[a-z]+>')
def
 callback(name):
   ...
name是一个正则表达式参数变量。

@root.route('/static/<path:path>')
def
 callback(path):
    
return static_file(path, root='static')
定义路径,类似Django中的静态文件路径,主要是定义文件在服务器存储中的位置。

root指定的是项目中的一个目录,这里指定了项目中的static,在这个目录下有testcss.css文件,可以访问:

修改一下:

如果root为'static'不变,还可以这样访问:

对于路由对应的函数,除了返回字符串,还可以使用模板:

@root.route('/hello/')
# 装饰器,定义了URL,即/hello/这个url由index这个函数来处理
def index():# return "Hello World!"return template('<b>Hello {{name}}!</b>',name="小花")

对于template(),除了像上面直接在其中写模板外,还可以直接指定一个模板文件,如

return template(‘index.html’)

创建index.html文件。这里要注意的是默认bottle找模板的路径,在bottle中有如下配置变量

TEMPLATE_PATH = ['./', './views/'],即默认模板查找顺序是先在项目根目录,然后是views目录,我们可以添加自己定义的目录

最终程序:

from bottle import template,Bottle,static_file
import bottle
bottle.TEMPLATE_PATH.append('./templates/')root = Bottle()# 装饰器,定义了URL,即/hello/这个url由index这个函数来处理
@root.route('/hello/')
def index():print(bottle.TEMPLATE_PATH)# return "Hello World!"# return template('<b>Hello {{name}}!</b>',name="小花")return template("index.html")@root.route('/sta/<path:path>')
def callback(path):return static_file(path,root='static')root.run(host='localhost', port=8080)

运行程序后,打印的TEMPLATE_PATH为:['./', './views/', './templates/'],但是却找不到模板文件:

经过反复的测试,查找资料,这个问题我个人的理解是:

这个路径是linux系统的路径,在windows系统下失去效果,windows系统下,需要添加windows的绝对路径,使用os.path.abspath(os.path.join(os.path.dirname(__file__), "views")来获取windows下的绝对路径:

from bottle import run,template,Bottle,TEMPLATE_PATH
import os
app = Bottle()
TEMPLATE_PATH.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "templates")))
TEMPLATE_PATH.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "views")))
print(TEMPLATE_PATH)@app.route('/')
@app.route('/hello/<name>')
def index(name='default'):return template('hello.html',name=name)run(app,host='localhost',port=8080)

这时的TEMPLATE_PATH为:

['D:\\website\\bottlepro\\templates', './', './views/', 'D:\\website\\bottlepro\\views']

这时再访问,就没有问题了。

请求方法路由

@root.route('/hello/', method='POST')
def index():
    ...
 
@root.get('/hello/')
def index():
    ...
 
@root.post('/hello/')
def index():
    ...
 
@root.put('/hello/')
def index():
    ...
 
@root.delete('/hello/')
def index():
    ...

一个简单的登陆:

from bottle import template,Bottle,static_file,TEMPLATE_PATH,request,redirect
import osTEMPLATE_PATH.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'templates')))
root = Bottle()# 装饰器,定义了URL,即/hello/这个url由index这个函数来处理
@root.route('/login/',method=['GET','POST'])
def login():if request.method == "GET":return template('login.html')else:# v = request.forms  # POST的数据都保存# v = request.query  # GET发来的请求数据# v = request.body   # POST发来的请求数据u = request.forms.get('user')p = request.forms.get('pwd')print(u,p)return redirect('/index/')
@root.route('/index/')
def index():return template('index.html')@root.route('/sta/<path:path>')
def callback(path):return static_file(path,root='static')root.run(host='localhost', port=8080)
# 这里就是启动webserver服务器,然后等待请求
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>Bottle登录</h1><form action="/login/" method="post"><input type="text" name="user" placeholder="用户名"><input type="password" name="pwd" placeholder="密码"><input type="submit" value="提交"></form>
</body>
</html>

Bottle中的request其实是一个LocalReqeust对象,其中封装了用户请求的相关信息:

request.headers     :    请求头信息

request.query         :    get请求信息

request.forms         :     post请求信息

request.files            :    上传文件信息

request.params       :     get和post请求信息

request.GET             :     get请求信息

request.POST           :     post和上传信息

request.cookies        :     cookie信息     

request.environ        :     环境相关相关

bottle的模板,在使用for循环遍历列表生成<ul><li>时的问题:

@root.route('/index/')
def index():user_list = [{'id': 1, 'name': 'root1', 'age': 18},{'id': 2, 'name': 'root2', 'age': 19},{'id': 3, 'name': 'root3', 'age': 20},{'id': 4, 'name': 'root4', 'age': 21},]return template('index.html', user_list=user_list)

模板index.html:

<body>{{user_list}}<hr/><ul>% for item in user_list :<li>{{item}}<li/>% end</ul>
</body>

预想的是这样:

实际是这样:

多出来的这些空行,都是<li>::marker</li>,为何会多产生这些标签??怎么去掉?希望高手指点一二。

Flask:

基本框架与Bottle差不多,如下:

from flask import Flaskapp = Flask(__name__)@app.route('/index/')
def index():return "hello world!"if __name__ == "__main__":app.run()

启动后:

默认是在5000端口。访问:

在Flask()中,可以对静态文件和模板路径进行配置:相关参数如下

默认模板路径就是templates,

这个不像Bottle,项目下创建了templates,就可以直接找到。

传递参数:

@app.route('/index/')
def index():# return "hello world!"return render_template('flaskindex.html',k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17})

模板:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>Flask index</h1>{{k1}} <!-- 单值 -->{{k2}} <!-- 列表 --><hr/><ul>{% for item in k2 %}<li>{{item}}</li>{% endfor %}</ul>{{k3}} <!-- 字典 --><hr/>{% for k,v in k3.items() %}{{k}}--{{v}}<br>{% endfor %}
</body>
</html>

还可以传递函数:

模板中:要在变量后加上小括号

Flask的动态路由方式:

  • @app.route('/user/<username>')
  • @app.route('/post/<int:post_id>')
  • @app.route('/post/<float:post_id>')
  • @app.route('/post/<path:path>')
  • @app.route('/login', methods=['GET', 'POST'])

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

与bottle一样,也有方法请求路由,即在路由中增加“method=”参数

对于Http请求,Flask会讲请求信息封装在request中(werkzeug.wrappers.BaseRequest),提供的如下常用方法和字段以供使用:

request.method
request.args
request.form
request.values
request.files
request.cookies
request.headers
request.path
request.full_path
request.script_root
request.url
request.base_url
request.url_root
request.host_url
request.host

Flask中使用cookie:使用make_response函数包装render_template,生成的对象有set_cookie方法。先导入make_response

@app.route('/index/')
def index():# return "hello world!"# return render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17})obj = make_response(render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17}))obj.set_cookie('usern','xiaohua')return obj

Flask中重定向:redirect

url_for(别名),这里的别名就是函数名,不需要在route中单独定义

Flask中使用session,先导入session,from flask import session

要使用session,需要先配置一个SECRET_KEY,在Flask对象上设置,设置后才能在函数中使用:session['key']=value的方式

from flask import Flask,render_template,make_response,session,request,redirect,url_forapp = Flask(__name__)
app.config.update(SECRET_KEY=b'_5#y2L"F4Q8z\n\xec]/') # 要使用session,必须设置这个参数def myfun():return "<a>测试传递函数</a>"@app.route('/index/')
def index():# return "hello world!"# return render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17})obj = make_response(render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17}))obj.set_cookie('usern','xiaohua')return obj@app.route('/login/',methods=['GET','POST'])
def login():if request.method =='POST':session['user'] = request.form.get('user') # 设置session内容url = url_for('redirectaliastest')return redirect(url)else:return render_template('login.html')@app.route('/testurlfor')
def redirectaliastest():print(session)  # login中设置的session在这里能打印出return render_template('flaskindex.html')if __name__ == "__main__":app.run()

关于Flask的中间件调用机制:

所有的WSGI在执行时,即实例化时,要先执行__call__()方法,

def __call__(self, environ: dict, start_response: t.Callable) -> t.Any:return self.wsgi_app(environ, start_response)

这个方法返回的是是执行wsgi_app方法的结果,然后在进入到Flask。

我们可以将这个wsgi_app换成我们自定义的类,在__call__方法中添加我们自己的代码,最后在调用原来的wsgi_app,这样就在请求处理前,先经过了我们自己的处理,像Django的中间件就是这种机制实现的。

from flask import Flask,render_template,make_response,session,request,redirect,url_forapp = Flask(__name__)
app.config.update(SECRET_KEY=b'_5#y2L"F4Q8z\n\xec]/')def myfun():return "<a>测试传递函数</a>"@app.route('/index/')
def index():# return "hello world!"# return render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17})obj = make_response(render_template('flaskindex.html',k0=myfun,k1='hello',k2=['a','b','c'],k3={'name':'haha1','age':17}))obj.set_cookie('usern','xiaohua')return obj@app.route('/login/',methods=['GET','POST'])
def login():if request.method =='POST':session['user'] = request.form.get('user')url = url_for('redirectaliastest')return redirect(url)else:return render_template('login.html')@app.route('/testurlfor')
def redirectaliastest():print(session)return render_template('flaskindex.html')class Foo:def __init__(self,w):self.w = wdef __call__(self, environ,start_response):print("自己的中间件")obj = self.w(environ,start_response)return obj
if __name__ == "__main__":app.wsgi_app = Foo(app.wsgi_app)  # 将原来的wsgi_app换成我们的类,Foo加上括号,即Foo()会先init,然后call# call的时候先执行我们的逻辑(相当于中间件),最后执行原来的wsgi_app# 这种方法有点装饰器的设计模式app.run()

启动后,页面请求过程:

Flask的消息:取一次就消失:

放置在session中,使用flash(value),取用,get_flashed_message(),取完就删除了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/89936.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多线程的学习中篇下

volatile 关键字 volatile 能保证内存可见性 volatile 修饰的变量, 能够保证 “内存可见性” 示例代码: 运行结果: 当输入1(1是非O)的时候,但是t1这个线程并沿有结束循环, 同时可以看到,t2这个线程已经执行完了,而t1线程还在继续循环. 这个情况,就叫做内存可见性问题 ~~ 这…

Java8实战-总结37

Java8实战-总结37 默认方法不断演进的 API初始版本的 API第二版 API 默认方法 传统上&#xff0c;Java程序的接口是将相关方法按照约定组合到一起的方式。实现接口的类必须为接口中定义的每个方法提供一个实现&#xff0c;或者从父类中继承它的实现。但是&#xff0c;一旦类库…

Qt扩展-KDDockWidgets 的使用

KDDockWidgets 的使用 一、概述二、原理说明三、代码实例1. 项目简述2. 布局源码 一、概述 KDDockWidgets 的使用相对比较简单&#xff0c;建议直接参考 其提供的例子。 二、原理说明 在这种多窗口布局显示的使用最常用的就是这两个类&#xff0c; 也就是 MainWindow 和 Doc…

MySQL 开启配置binlog以及通过binlog恢复数据

目录 一、binlog日志基本概念二、开启binlog日志记录2.1、查看binlog日志记录启用状态2.2、开启配置binlog日志 三、制作测试数据&#xff08;可以先不执行&#xff0c;这里是为后续数据恢复做准备&#xff0c;先看数据恢复流程&#xff09;四、使用binlog日志恢复数据4.1、前置…

中秋特辑——3D动态礼盒贺卡(可监听鼠标移动)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

ROS的通信机制

ROS是一个分布式框架&#xff0c;为用户提供多节点&#xff08;进程&#xff09;之间的通信服务&#xff0c;所有软件功能和工 具都建立在这种分布式通信机制上&#xff0c;所以ROS的通信机制是最底层也是最核心的技术。在大多数应用场景下&#xff0c;尽管我们不需要关注底层通…

7.网络原理之TCP_IP(下)

文章目录 4.传输层重点协议4.1TCP协议4.1.1TCP协议段格式4.1.2TCP原理4.1.2.1确认应答机制 ACK&#xff08;安全机制&#xff09;4.1.2.2超时重传机制&#xff08;安全机制&#xff09;4.1.2.3连接管理机制&#xff08;安全机制&#xff09;4.1.2.4滑动窗口&#xff08;效率机制…

软件测试面试经验分享,真实面试题

前言 本人普通本科计算机专业&#xff0c;做测试也有3年的时间了&#xff0c;讲下我的经历&#xff0c;我刚毕业就进了一个小自研薪资还不错&#xff0c;有10.5k&#xff08;个人觉得我很优秀&#xff09;&#xff0c;在里面呆了两年&#xff0c;积累了一些的经验和技能&#…

Flink Batch SQL Improvements on Lakehouse

本文整理自阿里云研发工程师刘大龙&#xff08;风离&#xff09;&#xff0c;在 Streaming Lakehouse Meetup 的分享。内容主要分为三个部分&#xff1a; Flink Batch on Paimon 挑战Flink Batch 核心优化后续规划 点击查看原文视频 & 演讲PPT 一、Flink Batch on Paimon 挑…

启动 React APP 后经历了哪些过程

本文作者为 360 奇舞团前端开发工程师 前言 本文中使用的React版本为18&#xff0c;在摘取代码的过程中删减了部分代码&#xff0c;具体以源代码为准。 在React 18里&#xff0c;通过ReactDOM.createRoot创建根节点。并且通过调用原型链上的render来渲染。 本文主要是从以下两个…

Spring实现简单的Bean容器

1.BeanDefinition&#xff0c;用于定义 Bean 实例化信息&#xff0c;现在的实现是以一个 Object 存放对象 public class BeanDefinition {/*** bean对象*/private Object bean;/*** 存放 &#xff08;定义&#xff09;Bean 对象*/public BeanDefinition(Object bean) {this.bea…

长期用眼不再怕!NineData SQL 窗口支持深色模式

您有没有尝试过被明亮的显示器闪瞎眼的经历&#xff1f; 在夜间或低光环境下&#xff0c;明亮的界面会导致许多用眼健康问题&#xff0c;例如长时间使用导致的眼睛疲劳、干涩和不适感&#xff0c;同时夜间还可能会抑制褪黑素分泌&#xff0c;给您的睡眠质量带来影响。 这些问…

​比特币ETF将迎来审核窗口期

作者&#xff1a;Greg Cipolaro&#xff0c;NYDIG 全球研究主管 编译&#xff1a;WEEX Exchange 几只重要的 ETF 申请将于 10 月中旬迎来审核窗口&#xff0c;本文通过观察近期期权市场的动态&#xff0c;以研究交易者对这些关键 ETF 日期的仓位态度&#xff1b;门头沟&#xf…

Vue3 + TS 自动检测线上环境 —— 版本热更新提醒

&#x1f414; 前期回顾 编写 loading、加密解密 发布NPM依赖包&#xff0c;并实施落地使用_彩色之外的博客-CSDN博客 目录 &#x1f30d; 问题产生 &#x1f916; 性能效率 &#x1fa82; 新建 autoUpdate.ts &#x1f38b; 在App.vue使用 &#x1f30d; 问题产生 当用…

《扩散模型 从原理到实战》Hugging Face (二)

第二章 Hugging Face简介 本章无有效内容 第三章 从零开始搭建扩散模型 有时候&#xff0c;只考虑事情最简单的情况反而更有助于理解其工作原理。本章尝试从零开始搭建廓庵模型&#xff0c;我们将从一个简单的扩散模型讲起&#xff0c;了解其不同部分的工作原理&#xff0c;…

IntelliJ IDEA快速查询maven依赖关系

1.在Maven窗口中点击Dependencies->show Dependencies 2.得到依赖关系图 此时原有快捷键Ctrlf可以查询jar包&#xff0c;如果没有查询菜单出来则设置快捷键方式为 File->Settings->Keymap->搜索栏输入find->在Main Menu下Edit下Find下Find双击算则Add keyboard…

云可观测性安全平台——掌动智能

云可观测性安全平台是一个跨架构、跨平台的可观测性方案&#xff0c;实现对云环境下的细粒度数据可视化&#xff0c;满足安全部门对云内部安全领域的多场景诉求&#xff0c;包括敏感数据动态监管、云网攻击回溯分析、攻击横移风险监控、云异常流量分析。本文将介绍掌动智能云可…

Oracle 11g_FusionOS_安装文档

同事让安装数据库&#xff0c;查询服务器信息发现操作系统是超聚变根据华为openEuler操作系统更改的自研操作系统&#xff0c;安装过程中踩坑不少&#xff0c;最后在超聚变厂商的技术支持下安装成功&#xff0c;步骤可参数该文。 一、 安装环境准备 1.1 软件下载 下载地址:…

ubuntu 20 安装 CUDA

1. 查看需要安装的cuda版本 nvidia-smi cuda的版本信息如下图所示 2. 去官网下载对应版本的CUDA 官网&#xff1a;CUDA Toolkit Archive | NVIDIA Developer 弹出以下界面&#xff0c;依次点击以下按钮 得到以下内容&#xff1a; 复制下载链接&#xff0c;下载cuda11到本…

Selenium Webdriver自动化测试框架

最近正在编写selenium webdriver自动化框架&#xff0c;经过几天的努力&#xff0c;目前基本已经实现了一套即能满足数据驱动、又能满足Web关键字驱动的自动化框架&#xff08;主要基于 antjenkinstestngselenium webdriverjxl实现&#xff09;。通过这次的自动化框架开发&…