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.xdnf.cn/news/144329.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

conan入门(二十七):因profile [env]字段废弃导致的boost/1.81.0 在aarch64-linux-gnu下交叉编译失败

今天在尝试用conan 1.60.0使用aarch64-linux-gnu编译器交叉编译boost/1.81.0时报错了&#xff1a; conan install boost/1.81.0 -pr:h aarch64-linux-gnu.jinja -pr:b default --build boost输出如下&#xff1a; Configuration (profile_host): [settings] archarmv8 arch_b…

SQL做流水号

SELECT REPLICATE(0, 3 - LEN(3)) 3 AS 流水号 SELECT REPLICATE(0, 5 - LEN(3)) 3 AS 流水号 SELECT REPLICATE(0, 8 - LEN(3)) 3 AS 流水号

Java中String转换为double类型

这次的java作业是写一个数字转换的小项目&#xff0c;其中从输入框中获取的是String类型&#xff0c;但是要进行数字操作&#xff0c;此时要用到很多操作String类型数据的方法了。 从javafx输入框中获取到String类型后&#xff0c;首先是要判断是否能转换为数字或者小数形式&a…

实验三十三、三端稳压器 LM7805 稳压性能的研究

一、题目 LM7805 输出电压、电压调整率、电流调整率以及输出纹波电压的研究。 二、仿真电路 电路如图1所示。集成稳压芯片采用 LM7805CT。 三、仿真内容 &#xff08;1&#xff09;测量图1&#xff08;a&#xff09;LM7805CT 的电压调整率&#xff0c;测量条件为 I O 50…

嵌入式Linux应用开发-基础知识-第十七章异常与中断的概念及处理流程

嵌入式Linux应用开发-基础知识-第十七章异常与中断的概念及处理流程 第十七章 异常与中断的概念及处理流程17.1 中断的引入17.1.1 妈妈怎么知道孩子醒了17.1.2 嵌入系统中也有类似的情况 17.2 中断的处理流程17.3 异常向量表17.4 参考资料 第十七章 异常与中断的概念及处理流程…

【C语言】快速排序

文章目录 一、hoare版本二、挖坑法三、前后指针法四、非递归快排五、快速排序优化1、三数取中选key值2、小区间优化 六、代码测试 一、hoare版本 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&#xff1a;任取待排序元素序列中的某元素…

今天刷到一条有用的抖音---网站文档copy的解禁

有的时候在网上查找一些资料&#xff0c;发现些有用的东西的时候&#xff0c;兴高采烈的复制一下&#xff0c;然后网站弹出一个菜单让你付钱~~如下图&#xff1a; 此时&#xff0c;可以在该网页上&#xff0c;按F12&#xff0c;召唤出调试窗口&#xff0c;在事件监听器中&#…

美国零售电商平台Target,值得入驻吗?如何入驻?

Target 是美国最大的零售商之一&#xff0c;在品牌出海为大势所趋的背景下&#xff0c;它在北美电商中的地位节节攀升。Target 商店在众多垂直领域提供各种价格实惠的自有品牌&#xff0c;吸引越来越多的跨境商家入驻&#xff0c;如美妆、家居、鞋服、日用百货等&#xff0c;随…

【STM32笔记】HAL库I2C通信配置、读写操作及通用函数定义

【STM32笔记】HAL库I2C通信配置、读写操作及通用函数定义 文章目录 I2C协议I2C配置I2C操作判断I2C是否响应I2C读写 附录&#xff1a;Cortex-M架构的SysTick系统定时器精准延时和MCU位带操作SysTick系统定时器精准延时延时函数阻塞延时非阻塞延时 位带操作位带代码位带宏定义总…

Python爬虫教程——解析网页中的元素

前言&#xff1a; 嗨喽~大家好呀&#xff0c;这里是小曼呐 ~ 在我们理解了网页中标签是如何嵌套&#xff0c;以及网页的构成之后&#xff0c; 我们就是可以开始学习使用python中的第三方库BeautifulSoup筛选出一个网页中我们想要得到的数据。 接下来我们了解一下爬取网页信息…

基于自适应启动策略的混合交叉动态约束多目标优化算法(MC-DCMOEA)求解CEC2015/CEC2018/CEC2023(MATLAB代码)

一、动态多目标优化问题 1.1问题定义 1.2 动态支配关系定义 二、 基于自适应启动策略的混合交叉动态多目标优化算法 基于自适应启动策略的混合交叉动态多目标优化算法&#xff08;Mixture Crossover Dynamic Constrained Multi-objective Evolutionary Algorithm Based on Se…

高速数字化仪为您带来高效RF测量秘籍!

模块数字化仪能够以16 bit高分辨率采集2 GHz带宽的RF信号。虹数字化仪能够使用许多RF和较低频率微波的测试。本文重点介绍使用虹科数字化仪进行RF测量相关内容。 高数据通量测试 基于多通道PCIe的数字化仪&#xff0c;可以以高达12.8 GBytes/s的速度传输数据&#xff0c;从而…

云中网络的隔离GREVXLAN

底层的物理网络设备组成的网络我们称为 Underlay 网络&#xff0c;而用于虚拟机和云中的这些技术组成的网络称为 Overlay 网络&#xff0c;这是一种基于物理网络的虚拟化网络实现。 第一个技术是 GRE&#xff0c;全称 Generic Routing Encapsulation&#xff0c;它是一种 IP-o…

Serverless 数仓技术与挑战(内含 PPT 下载)

近期&#xff0c;Databend Labs 联合创始人张雁飞发表了题为「Serverless 数仓技术与挑战」的主题分享。以下为本次分享的精彩内容&#xff1a; 主题&#xff1a; 「Serverless 数仓技术与挑战」 演讲嘉宾&#xff1a; 张雁飞 嘉宾介绍&#xff1a; Databend Labs 联合创始人…

c++迷宫小游戏

一、总结 一句话总结&#xff1a; 显示&#xff1a;根据map数组输出图像 走动&#xff1a;修改map数组的值&#xff0c;每走一步重新刷新一下图像就好 1、如果走函数用z()&#xff0c;出现输入s会向下走多步的情况&#xff0c;原因是什么&#xff1f; 向下走两层循环ij增加&a…

openlayers-18-聚合显示补充(切换聚合与非聚合状态)

最近有一些网友问我&#xff0c;聚合显示怎么实现聚合与不聚合之间的切换&#xff0c;有很多方法能够实现&#xff0c;下面是一个示例作为参考。 <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-…

LabVIEW开发低成本静脉监测和控制输液系统

LabVIEW开发低成本静脉监测和控制输液系统 信息技术的使用和进步彻底改变了现代医疗保健的面貌。医院、疗养院和其他姑息治疗院需要不同的人力资源&#xff0c;如医生、技术人员、护士和其他工作人员&#xff0c;他们共同提供最先进的医疗保健。COVID-19大流行表现出严重缺乏此…

【Linux学习】04Linux实用操作

Linux&#xff08;B站黑马&#xff09;学习笔记 01Linux初识与安装 02Linux基础命令 03Linux用户和权限 04Linux实用操作 文章目录 Linux&#xff08;B站黑马&#xff09;学习笔记前言04Linux实用操作各类小技巧&#xff08;快捷键&#xff09;ctrl c 强制停止ctrl d 退出或…

MySQL - group by分组查询 (查询操作 三)

功能介绍 group by: 对数据进行分组和聚合操作(可以操作单字段和多字段) having&#xff1a;过滤group by的结果&#xff0c;也就是在分组后添加筛选条件 基础语法 select 字段列表 from 表名 [ where 条件 ] group by 分组字段名 [ having ]; where 和 having的区…

ROS系统通过类定义实现数据处理并重新发布在另一话题

在实际应用中&#xff0c;经常需要在同一个节点内接受数据&#xff0c;在回调函数中将数据进行处理&#xff0c;再将新数据重新发布在另一个新话题上。 实现步骤&#xff1a; 1. 定义一个数据处理类SubscribeAndPublish&#xff0c;设置2个pub成员对象和1个sub成员对象为publ…