Flask 框架学习_1
Flask 框架 与 Django框架区别
Flask:
- 小巧、灵活,让程序员自己决定定制哪些功能,非常适用于小型网站。
- 对于普通的工人来说将毛坯房装修为城市综合体还是很麻烦的,使用Flask来开发大型网站也一样,开发的难度较大,代码架构需要自己设计,开发成本取决于开发者的能力和经验。
Django:
- 大而全,功能极其强大,是Python web框架的先驱,用户多,第三方库极其丰富。
- 非常适合企业级网站的开发,但是对于小型的微服务来说,总有“杀鸡焉有宰牛刀”的感觉,体量较大,非常臃肿,定制化程度没有Flask高,也没有Flask那么灵活。
安装 flask
法一:
pip install flask
法二:
Falsk的目录结构(建议)
flask-demo/
├ run.py # 应用启动程序
├ config.py # 环境配置
├ requirements.txt # 列出应用程序依赖的所有Python包
├ tests/ # 测试代码包
│ ├ __init__.py
│ └ test_*.py # 测试用例
└ myapp/
├ admin/ # 蓝图目录
├ static/
│ ├ css/ # css文件目录
│ ├ img/ # 图片文件目录
│ └ js/ # js文件目录
├ templates/ # 模板文件目录
├ __init__.py
├ forms.py # 存放所有表单,如果多,将其变为一个包
├ models.py # 存放所有数据模型,如果多,将其变为一个包
└ views.py # 存放所有视图函数,如果多,将其变为一个包
创建一个最简单的WEB页面“Helle word”
from flask import Flask
app = Flask(__name__)
@app.route('/') # @app.route('/')设置网站的url路由
def hello_world():
return 'hello world'
if __name__ == '__main__':
app.run(host='127.0.0.1',port=5000)
运行该文件,然后访问127.0.0.1:5000 或者 localhost:5000 ,我们应当可以看到浏览器上输出了hello world。 这里首先引入了Flask类,然后给这个类创建了一个实例,name代表这个模块的名字。因为这个模块是直接被运行的所以此时name的值是main。然后用route()这个修饰器定义了一个路由,告诉flask如何访问该函数。最后用run()函数使这个应用在服务器上运行起来。
route()装饰器
路由通过使用Flask的route()的装饰器来设置的,告诉 Flask 哪个 URL 应该触发我们的函数。
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World'
if __name__ == '__main__':
app.run(host='127.0.0.1',port=5000)
如果希望获取/article/1这样的路径参数,就需要使用路径变量。路径变量的语法是/path/<converter:varname> 。在路径变量前还可以使用可选的转换器,有以下几种转换器。
转换器 | 作用 |
---|
string | 默认选项,接受除了斜杠之外的字符串 | int | 接受整数 | float | 接受浮点数 | path | 和string类似,不过可以接受带斜杠的字符串 | any | 匹配任何一种转换器(可以同时指定多种路径) | uuid | 接受UUID类型的字符串 |
特别说明: 一般情况下参数中不能含有 / ,想要含有/ ,必须限制为path 类型。除此区别外与string 类型用法一致。
举例说明:
from flask import Flask
app = Flask(__name__)
@app.route('/user/<username>') # 默认类型为string
def show_user_profile(username): # 请求地址为:http://127.0.0.1:5000/user/ + 任意字符传
# show the user profile for that user
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id): # 请求地址为:http://127.0.0.1:5000/post/ + 整数int
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
@app.route('/path/<path:subpath>')
def show_subpath(subpath): # 请求地址为:http://127.0.0.1:5000/path/ + 喜欢string但也接受斜线
# show the subpath after /path/
return 'Subpath %s ' % subpath
if __name__=='__main__':
app.run(debug=True)
示例:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/corley')
def hello_corley():
return '这是我的第一个Flask页面'
@app.route('/list/<int:aid>')
def article_list(aid):
return '这是第{}篇文章'.format(aid)
@app.route('/list/<path:aid>')
def comment_list(aid):
return '这是第{}个评论'.format(aid)
@app.route('/<any(notice,follow):url_path>/') #url_path是变量,此时定义路由时需要在路径最后加 / 才能访问.
def message(url_path):
if url_path == 'notice':
return '当前路径是notice'
else:
return '当前路径是follow'
if __name__ == '__main__':
app.run(debug=True)
显示: 如果不想指定子路径来传递参数,也可以通过 ?=的形式来传递参数,例如:/article?id=xxx ,这种情况下,可以通过request.args.get('id') 来获取id的值。如果是post方法,则可以通过request.from.get('id') 来进行获取。 在flask中添加这类的地址参数需要先从flask中导入request,示例如下:
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/corley')
def hello_corley():
return '这是我的第一个Flask页面'
@app.route('/list/<int:aid>')
def article_list(aid):
return '这是第{}篇文章'.format(aid)
@app.route('/list/<path:aid>')
def comment_list(aid):
return '这是第{}个评论'.format(aid)
@app.route('/<any(notice,follow):url_path>/')
def message(url_path):
return url_path
@app.route('/wd')
def baidu_search():
return request.args.get('keyword')
if __name__ == '__main__':
app.run(debug=True)
显示(通过 ?=的形式来传递参数):
URL的唯一性和重定向行为
以下两个例子在尾随斜杠的使用上有所不同。
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
projects 尾部URL有一个尾部斜杠。它类似于文件系统中的文件夹。如果您访问的 URL 没有尾部斜杠 ( /projects),Flask 会将您重定向到带有尾部斜杠 ( /projects/)的规范 URL 。
about 尾部URL没有尾部斜杠。它类似于文件的路径名。访问带有斜杠 ( /about/)的 URL会产生 404“未找到”错误。这有助于保持这些资源的 URL 唯一,这有助于搜索引擎避免将同一页面索引两次。
URL构建:url_for()函数
在Web程序中常常需要获取某个页面的URL,在Flask中需要使用url_for(‘方法名’)来生成对应方法的URL。
为什么要使用 URL 反转功能来构建 URL, url_for()而不是将它们硬编码到模板中?
- 反转通常比硬编码 URL 更具描述性。
- 您可以一次性更改 URL,而无需记住手动更改硬编码的 URL。
- URL 构建透明地处理特殊字符的转义。
- 生成的路径总是绝对的,避免了浏览器中相对路径的意外行为。
- 如果您的应用程序放置在 URL 根目录之外,例如,在 /myapplication而不是 中/,url_for()则会为您正确处理。
url_for() 和 redirect 的区别
可以使用程序 URL 映射中保存的信息生成 URL。url_for() 函数最简单的用法是以视图函数名作为参数, 返回对应的 URL。例如,在示例程序中 hello.py 中调用 url_for('index') 得到的结果是 /。
redirect 是重定向函数,输入一个URL后,自动跳转到另一个URL所在的地址,例如,你在函数中写return redirect('https://www.baidu.com') 页面就会跳转向百度页面。
from flask import url_for
@app.route('/')
def index():
return 'index'
@app.route('/login')
def login():
return 'login'
@app.route('/baidu') # 访问该地址会被重定向到:www.baidu.com
def login():
return redirect('https://www.baidu.com')
@app.route('/user/<username>')
def profile(username):
return 'user{}'.format(username)
with app.test_request_context():
print(url_for('index'))
print(url_for('login'))
#将未知变量next添加到 URL 末尾作为查询参数
print(url_for('login', next='/'))
#将 URL 规则中对应的变量 username 作为参数
print(url_for('profile', username=''John Doe''))
/
/login
/login?next=/ # ? 后面代表传参
/user/John%20Doe # %20 表示空格
DEBUG模式
我们修改代码中的输出,然后查看浏览器上是否有变化。如果你照做的话,可以看到什么变化都没有。其实Flask内置了调试模式,可以自动重载代码并显示调试信息。这需要我们开启调试模式,方法很简单,设置FLASK_DEBUG环境变量,并将值设置为1。或者设置app.debug=True。
from flask import Flask
app = Flask(__name__)
app.debug=True
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/login')
def login():
return 'Login'
if __name__ == '__main__':
app.run(host='127.0.0.1',port=5000)
# app.run() # app.run()是让flask项目运行起来,可以指定主机号和端口号。默认的host是:127.0.0.1,默认端口号:5000。host:0.0.0.0可以让其他电脑也能访问到该网站,port指定访问的端口。
然后再次运行程序,会看到有这样的输出。这时候如果再次修改代码,会发现这次Flask会自动重启。
1. Debug mode: on
2. Restarting with stat
3. Debugger is active!
4. Debugger PIN: 907-645-143
5. Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [21/Dec/2021 20:29:38] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/Dec/2021 20:30:20] "GET /login HTTP/1.1" 200 -
DEBUG方法:
# 在run()方法中设置debug参数为True
if __name__ == '__main__':
app.run(debug=True)
# 设置app对象实例的属性为True
if __name__ == '__main__':
app.debug = True
app.run()
# 通过配置参数config设置
# 因为app.config是flask.config.Config的实例,而Config类是继承自dict,因此可以通过updatae()方法进行配置
if __name__ == '__main__':
app.config.update(DEBUG=True)
app.run()
项目配置与配置文件
Flask项目配置,都是由app.config对象来进行配置的。 比如你要配置一个项目处于debug模式可以使用:app.config['DEBUG'] = True) 来进行配置,那么Flask项目将以DEBUG 模式来运行。
1. 直接硬编码
app = Flask(__name__)
app.config['DEBUG'] = True
硬编码的方式不灵活,不便于进行复用。
2.通过updata()方法
app.config.update(
DEBUG=True,
SECRET_KEY='...'
)
因为app.config是flask.config.Config的实例,而Config类是继承自dict,因此可以通过updatae() 方法进行配置
3.通过 from_object()方法
如果配置项特别多,可以把所有的配置项都放在一个模块中,然后通过加载模块的方式进行配置,假设有一个settings.py模块,专门用来存储配置项的,此你可以通过app.config.from_object() 方法进行加载,并且该方法既可以接收模块的的字符串名称,也可以模块对象。
# 1. 通过模块字符串
app.config.from_object('settings')
# 2. 通过模块对象
import settings
app.config.from_object(settings)
示例: 添加配置文件后,将配置项都放入该文件中,其他文件直接引用该配置文件中的配置项,提高了代码的复用性、降低了耦合度,同时,在配置文件中修改了配置项时,其他代码中均不需要修改,从而提高了代码的灵活性。
新建config.py文件,添加一些配置如下;
# 设置Debug模式为True
DEBUG = True
# 指定HOST
HOST = '127.0.0.1'
在Flask文件中导入:
from flask import Flask
import config
app = Flask(__name__)
# 装饰器,将当前路由映射到指定函数
@app.route('/')
def hello_world():
result = 1 / 0
return 'hello world'
if __name__ == '__main__':
app.config.from_object(config) # 导入配置项
app.run()
在运行,也能开启Debug模式。 也可以通过字符串形式导入,此时不需要导入config模块:
if __name__ == '__main__':
app.config.from_object('config')
app.run()
4.from_pyfile()方法
app.config.from_pyfile() 方法传入一个文件名,通常以.py结尾的文件,但是不限于只使用.py后缀的文件。 通过导入Python文件的形式导入配置文件:
if __name__ == '__main__':
app.config.from_pyfile('config.py')
app.run()
from_pyfile() 方法有一个silent 参数,设置为True时,如果配置文件不存在也不会报错。
|