构建一个Web应用:利用search4letters这个函数,让人们都可以在web上访问这个函数
区分好web请求与web响应:
1、用户在浏览器输入一个web地址后单击超链接,
2、浏览器会将用户的动作转换为一个web请求,通过互联网发送到一个web服务器。
3、web服务器接收到web请求后会做两件事:
如果请求知识请求一个静态内容(HTML文件或图像等),web服务器就会找到这个资源并将它作为一个web响应返回去给web浏览器;
如果请求的是动态内容(搜索结果或购物车等),web服务器就会运行一些代码来生成web响应再返回去给web浏览器。
4、web服务器通过互联网江响应发回给正在等待的web浏览器
5、浏览器接收到web响应并显示在用户屏幕上
分析search4letters:
def search4letters(phrase:str,letters:str='aeiou') -> set:
这个函数需要至少1个但不能超过2个参数,phrase和letters(要在phrase中搜索letters)。且letter参数是可选的(默认为aeiou)
Web应用框架flask
安装Flask:
windows:
打开命令行提示窗口,作为管理员运行(右键点击鼠标选择作为管理员运行),执行命令
c:\>py -3 -m pip install flask
回车后跑完会出现
Successfully installed Jinja-版本号 Markupsafe-版本号 Werkzeug-版本号 flask-版本号
Flsak 依赖的4个模块 Jinja-版本号 Markupsafe-版本号 Werkzeug-版本号 flask-版本号
轻量级规模小易使用是Flask模块的特性
启动服务器:
需要复习掌握常用命令行
第一种方法
使用win+R可以调出cmd,或者在目标文件的文件夹里面按住shift同时单击鼠标右键选择Open command window here
>d:(变动位置)
>cd (通过文件属性来查看文件的所属位置)(win10以上可以直接复制粘贴ctrl+c/v,win10以下只能右键复制粘贴)
>cd 文件位置 >python(空格) 文件名.py(如untitled.py) 启动python文件,如果没有配置python文件启动运行环境,就需要去以管理员身份更改PATH配置环境将python文件移动到pyrhon.exe所处的指定的根目录之下
第二种方法
使用Anoconda Prompt
>cd 位置粘贴(与第一种方法一样)
检查是否已经安装好flask框架
>flask
回车后代码跑起来结束就是已经安装好,如果没有的话就需要使用
pip install flask
从现在开始都会由Flask接管,只要内置Web服务器完成任何操作,都会在屏幕上显示状态校系。启动之后,Flask Web服务器会立即确认它已经启动,开始运行并在Flask测试Web地址(127.0.0.1)和协议端口(5000)上等待为Web请求提供服务。
启动服务器
>cd (进入目录路径) >python(空格)hello-flask.py(启动文件两种方法:第一种是将文件位置复制粘贴,第二种是将文件直接拖进命令行里面)
接着就会出现
*Running on http://127.0.0.1:5000/(Press CTRL+C to quit)(IP地址)
但是会报错
5000是端口号,网页默认是80不需要写出来
flask若在单机上是找不到服务器的
如果IP输入5000/dothiswork.html ,服务器就会多出一行404报错,因为没有5000的话用户就会找不到服务器
我们把IP地址输入打开也是可以跳转到网页的,因为已经Running起来了
将IP地址(URL)在浏览器上面输入并回车就会跳转到相应的web请求后返回的web响应页面,服务器就已经启动成功了。这就是Web浏览器和Web服务器交互。接着终端窗口会出现新的状态消息
200-
接下来我们编写一下代码文件
将代码输进去来获得第一个hello_flask.py文件
from flask import Flask
app = Flask (__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
app.run()
不能在IDLE中运行这个Flask代码,IDLE不能很好完成这种大的代码段,最好在系统的命令行上直接通过解释器运行代码。服务器启动流程看上面。
分析代码行
第一行:导入flask模块的Flask类
from flask import Flask
也可以写成
import flask
flask.Flask
第二行:创建一个Flask类型的对象,把它赋给app变量。
app = Flask (__name__)
Flask使用一个奇怪的参数 __ name __(双下划线),设置为当前活动模块的名字。创建一个新的Flask对象时,Flask类需要知道 __ name __的当前值,必须作为一个参数传递这个值。在这里需要注意”dunder name“的使用”双下划线,name,双下划线“
定制对象是app也就是实例,flask是变量类型代表网页
这里没有调用hello函数,并不是往服务器上放代码,而是@修饰符帮我们做了这一步骤
第三行:修饰符(decorator)可以调整一个现有函数的行为,而无需修改这个函数的代码(函数得到修饰,允许你根据需要为已有的一些代码增加额外的行为)
@app.route('/')
修饰符route前面有@符号前缀,可以调整一个已有函数的行为
后面(‘/’)是URL:127.0.0.1:5000
本行是通过app变量使用Flask的route修饰符。route修饰符允许你江一个URL Web 路径与一个已有的python函数关联。URL"/"与下一行代码中定义的函数关联,函数命名为hello,当一个只想“/”URL的请求到达服务器时route修饰符会安排Flask web服务器调用这个函数。route修饰符会等待所修饰的函数生成的输出,再将输出返回给服务器,服务器再将输出返回给正在等待的Web浏览器。
记住:Flask能为你完成所有这些工作,我们需要做的就是写一个函数生成我们想要的输出。Flask和route修饰符会负责所有具体细节。
注:@修饰符为上下文做了做了关联,当执行5000时,前面有了@自动帮你执行后面的函数,返回了Hello world(自动默认执行)
第四行:定义route修饰符修饰的函数,返回字符串 ->str
调用hello函数时返回消息“Hello world from Flask!”
def hello() -> str:
return 'Hello world from Flask!'
第五行:通过调用run来实现得到赋给app变量的Flask对象后,让Flask开始运行它的web服务器
app.run()
可以看到服务器返回了url,run后面的()。在服务器上跑起来,跑的是代码。请求的是一个str,返回值也是一个str。
这时,Flask会启动内置Web服务器,并在服务器中运行Web应用代码。Web服务器接收到指向“/”URL的任何请求时,会响应“Hello worldfrom Flask!”消息,而指向其他URL请求会得到404“Resourse not found”错误消息。
输入http://127.0.0.1:5000/doesthiswork.html,是没有页面并且服务器会同步报错404
浏览器显示“Not Found”,终端窗口运行的Web应用也会用一个适当的消息更新状态
在这里Flask为你做了什么:
他提供了一种机制,利用这种机制我们可以执行任何已有的python函数,并在一个Web浏览器中显示他的输出
为了向Web应用中增加更多功能,所要做的只是要确定希望将函数与哪个URL关联,然后在完成具体工作的函数上面编写一个适当的@app.route修饰符行
我们将使用上一章节的search4letters函数
我们现在来修改hello_flask.py来包含第二个URL: /search4。将这个URL与一个名为do_search的函数关联,它会从vsearch模块调用search4letters函数,让do_search函数返回搜索时确定的结果:在短语”life,the universe,and everything“中搜索字符串‘eiru,!’
注意:search4letters返回的结果是一个pytho集合,向等待的Web浏览器返回任何结果之前,一定要通过调用str内置函数(BIF)将结果强制转换为一个字符串。因为浏览器希望得到文本数据而不是一个python集合
修改后的
hello_flask2.py
from flask import Flask
from vsearch import search4letters
app = Flask (__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4')
def do_search() -> str:
return str(search4letters('life,the universe,and everything','eiru,'))
app.run()
增加一到第二行:
from vsearch import search4letters
在调用之前,需要从"vsearch"模块导入"search4letters"函数
增加二:
@app.route('/search4')
第二个修饰符建立"/search4"URL
增加三:
def do_search() -> str:
return str(search4letters('life,the universe,and everything','eiru,'))
”do_search“函数调用"search4letters",然后将结果作为字符串返回
想要测试新功能需要重启 Flask Web 应用,因为现在运行的是老版本的代码
返回到终端窗口,同时按下”Ctrl + c“,Web应用会停止,回到操作系统提示符,按向上箭头找到前一个命令(之前启动hello_flask.py的命令),回车
再次显示初始的Flask状态消息,确认更新后的Web应用在等待请求
输入http://127.0.0.1:5000正常
输入http://127.0.0.1:5000/search4正常
这是因为没有修改与默认‘/’URL关联的代码,所以这个功能仍能正常工作,会显示"Hello world from Flask!"消息——http://127.0.0.1:5000
如果在浏览器的地址栏输入”http://127.0.0.1:5000/search4“,就会看到调用了search4letters的结果
调用"search4letters"的结果,但是确实证明了使用"/search4"URL会调用函数并返回结果
set对象没有被调用,return返回字符串,强制为字符串,是一种集合类型的字符串
函数只会执行相近数,所以服务器会有多个页面,通过“/”反斜杠(默认IP地址)为它指定一个名字,我们在服务器上面搭建了两个东西分别是“/”,“/search4”
显示"search4"是"get"
200是正常
500服务器过载
404网页找不到
函数的修饰符只能够找到函数
团队的项目是将其他同学的作为一个模块导进来:
将py文件打包导出为模块,用主的py文件来做操作,基本上一个函数一个页面,注册信息是主界面,其他是分界面,每个同学都有页面前端和后端,项目都部署在码云里面并且要活跃该项目。但是必须要弄清楚主程序的入口和项目逻辑在哪里?
url解释:
用来访问Web 应用中的URL中的127.0.0.1和:5000是什么意思
为什么请求的是返回值而不是网页呢?Web应用需要一个Web页面接收输入,还需要一个Web页面显示结果(将输入提供给search4letters函数得到的结果)
关键是这两段的代码分别响应了两个网页
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4')
def do_search() -> str:
return str(search4letters('life,the universe,and everything','eiru,'))
这就要用到两个基模板了,在用基模板之前需要先修改hello函数来返回HTML表单,再修改do_search函数接收这个表单的输入,再调用search4letters函数,最后由do_search将结果作为另一个Web页面返回
利用模板引擎,可以应用面向对象的继承和重用概念来生成文本数据,Web页面也是其中之一。
两个基模板(网站的外观可以在一个顶层HTML模板中定义,这称为基模板,其它HTML页面继承这个模板。如果对基模板做了某个修改,这个修改就会在继承该模板的所有HTML页面中体现)
Flask提供的模板引擎为Jinja2。
基模板 base.html
注意标注出来的{{和}}之间,{%和%}包围是针对Jinja2模板引擎的
{{ the_title }}
{% block body %}
{% endblock %}
特别注意
#标准HTML5标记
{{ the_title }} #这是一个Jinja2指令,指示将在呈现之前提供的一个值(可以把它想象成是模板的一个参数)
#样式表定义了所有Web页面的外观
{% block body %} #Jinja2指令指示要在呈现之前替换这里的HTML块,这要由继承这个模板的页面来提供
{% endblock %} #Jinja2指令指示要在呈现之前替换这里的HTML块,这要由继承这个模板的页面来提供
有了基模板后,可以使用Jinja2的extends指令继承这个模板。这样继承模板的HTML文件只需要提供基模板中命名块的HTML。在这里我们只有一个命名块:body
第一个页面标记:entry.html
实现用户与这个HTML表单交互来提供Web应用需要的phrase和letters的值
这个文件中没有重复基模板中的样板HTML,因为extends指令已经为我们包含了这些标记。我们需要提供这个文件特定的HTML,所以要在名为body的Jinja2块中提供标记
{% extends 'base.html' %} #这个模板继承了基模板,为名为"body"的块提供了一个替代块
{% block body %}
{{ the_title }}
{% endblock %}
特别注意:
{% extends 'base.html' %}
{% block body %}
{{ the_title }}
{% endblock %}
第一个页面标记:results.html
实现呈现搜索的结果
{% extends 'base.html' %} #与entry.html类似,这个模板也继承了基模板,另外为名为"body"的块提供了一个替代块
{% block body %}
{{ the_title }}
You submitted the following data:
Phrase: {{ the_phrase }}
Letters: {{ the_letters }}
#注意the_phrase,the_letters,the_results 这些额外的参数值,在呈现之前是需要赋值给他们的。
When "{{the_phrase }}" is searched for "{{ the_letters }}", the following
results are returned:
{{ the_results }}
{% endblock %}
特别注意:
{% extends 'base.html' %}
{% block body %}
{{ the_title }}
{{ the_phrase }}
{{ the_letters }}
{{the_phrase }}
{{ the_letters }}"
{{ the_results }}
{% endblock %}
Web应用需要呈现两个Web页面,现在已经有了两个模板。这两个模板都继承自基模板,因此继承了基模板的外观,现在就是要呈现这些页面。两个页面的标题将在呈现时提供标题值来取代{{ the_title }}指令。可以把双大括号中的各个名字想成是模板的一个参数 P216
新增一个Flask的函数 render_template 的函数:如果指定一个模板名和所需的参数,调用这个函数时会返回一个HTML串,为此需要将这个函数名增加到从flask模块导入的函数列表中,再根据需要进行调用
将hello_flask.py文件的名字改为vsearch4web.py
#这是hello_flask.py里的代码
from flask import Flask
from vsearch import search4letters
app = Flask(__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4')
def do_search() -> str:
return str(search4letters('life, the universe, and everything', 'eiru,!'))
app.run()
为了呈现entry.html模板中的HTML表单,修改vsearch4web.py
#这是vsearch4web.py里的代码
from flask import Flask, render_template
from vsearch import search4letters
app = Flask(__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4')
def do_search() -> str:
return str(search4letters('life, the universe, and everything', 'eiru,!'))
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
app.run()
特别注意:
修改1:导入render_template函数
将“render_template”增加到从“flask”模块导入的函数列表
from flask import Flask, render_template
修改2:创建一个新的URL,这里就是/entry
每次你的Flask web应用中需要一个新的URL时,都要增加一个新的@app.route行。我们会在do_search函数之后,app.run()代码行前面增加这一行,为Web应用增加一个新URL
@app.route('/entry')
修改3:创建一个函数返回正确呈现的HTML
将这个函数增加到新“@app.route”行下面
有了@app.route行之后,可以为新增的URL关联代码,为此要创建一个完成具体工作的函数。这个函数要调用render_template函数(并返回它的输出),这里要传入模板文件名(这里是entry.html)以及模板所需的参数值(在这里需要为the_title提供一个值)
entry.html 提供要呈现的模板名
the_title='Welcome to search4letters on the web! 提供一个值与“the_title”参数关联
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
现在暂时还不能够运行。基模板引用一个名为hf.css的样式表,这个样式表要放在一个名为static的文件夹中,也就是说hf.css文件必须存在必须放在static文件夹中static文件夹必须放在webapp文件夹中,在基模板中有看到hf.css文件的路径
并且还要将基模板和两个模板(base.html、entry.html、results.html)都存储在templates文件夹中,templaes文件夹也在webapp文件夹中.
所以到现在有一个webapp文件夹,有5个文件(vsearch4web.py、hf.css、base.html、entry.html、results.html)和2个文件夹(static、templates)
放置好文件夹就可以运行了,先ctrl+c退出服务器停止web应用,再按向上箭头回到上一步输入文件名后按回车,出现running就是新代码开始运行,等待为请求提供服务。但是出了点错误
这段代码仍然支持 / 和 /search4 URL,如果使用一个浏览器请求这些URL,会得到相同的响应,但是如果输入
http://127.0.0.1:5000/entry
浏览器中显示的响应将是所呈现的HTML表单
命令行提示窗口会显示另外两个状态栏:
一个对应/entry请求(请求HTML表单)
另一个与浏览器对hf.css样式表的请求有关(请求样式表)
但是如果输入一个短语并调整要查找的字母值,点击do it 按钮时会出错
看到命令提示符我们需要区分get和post的不同之处,首先要了解http状态码
当web应用出现问题,web服务器就会响应一个http状态码并发送到浏览器中,http是允许web浏览器和服务器通信的协议,实际上,每个web请求都会生成一个http状态码响应 P222
100类-信息消息
200类-成功消息
300类-重定向消息
400类-客户端错误消息
500类-服务器错误消息
这里的405状态码指示客户端(浏览器)使用了这个服务器不允许的一个http方法来发送请求。http方法我们需要掌握2种:GET和POST
GET方法:
浏览器通常使用这个方法从web服务器请求一个资源,目前web应用中所有URL都支持GET,这是Flask默认的http方法
POST方法:
允许web浏览器向服务器通过http发送数据,这与HTML