Files
python-book/04.Flask/01.URL与视图.md
2025-08-27 14:39:37 +08:00

10 KiB
Raw Permalink Blame History

URL与视图

1. Flask简介

flask是一款非常流行的Python Web框架出生于2010年作者是Armin Ronacher,本来这个项目只是作者在愚人节的一个玩笑,后来由于非常受欢迎,进而成为一个正式的项目。

flask自2010年发布第一个版本以来大受欢迎深得开发者的喜爱目前在Github上的Star数已经超过55.5k了,有超Django之趋势。flask能如此流行的原因,可以分为以下几点:

  • 微框架、简洁、只做他需要做的,给开发者提供了很大的扩展性。
  • Flask和相应的插件写得很好用起来很爽。
  • 开发效率非常高,比如使用SQLAlchemyORM操作数据库可以节省开发者大量书写sql的时间。

Flask的灵活度非常之高,他不会帮你做太多的决策,一些你都可以按照自己的意愿进行更改。比如:

  • 使用Flask开发数据库的时候,具体是使用SQLAlchemy还是MongoEngine,选择权完全掌握在你自己的手中。区别于DjangoDjango内置了非常完善和丰富的功能,并且如果你想替换成你自己想要的,要么不支持,要么非常麻烦。
  • 把默认的Jinija2模板引擎替换成其他模板引擎都是非常容易的。

1.1 安装Flask

通过pip install flask即可安装。

1.2 第一个flask程序

pycharm新建一个flask项目,新建项目的截图如下:

img

点击create后创建一个新项目,然后在helloworld.py文件中书写代码:

#coding: utf8    

# 从flask框架中导入Flask类
from flask import Flask

# 传入__name__初始化一个Flask实例
app = Flask(__name__)

# app.route装饰器映射URL和执行的函数。这个设置将根URL映射到了hello_world函数上
@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    # 运行本项目host=0.0.0.0可以让其他电脑也能访问到该网站port指定访问的端口。默认的host是127.0.0.1port为5000
    app.run(host='0.0.0.0',port=9000)

然后点击运行,在浏览器中输入http://127.0.0.1:9000就能看到hello world了。需要说明一点的是,app.run这种方式只适合于开发,如果在生产环境中,应该使用Gunicorn或者uWSGI来启动。如果是在终端运行的,可以按ctrl+c来让服务停止。

2. 项目配置

2.1 设置为DEBUG模式

默认情况下flask不会开启DEBUG模式,开启DEBUG模式后flask会在每次保存代码的时候自动的重新载入代码并且如果代码有错误会在终端进行提示。

img

如果一切正常,会在终端打印以下信息:

* Restarting with stat
* Debugger is active!
* Debugger pin code: 294-745-044
* Running on http://0.0.0.0:9000/ (Press CTRL+C to quit)

需要注意的是,只能在开发环境下开启DEBUG模式,因为DEBUG模式会带来非常大的安全隐患。

2.2 配置文件

Flask项目的配置,都是通过app.config对象来进行配置的。比如要配置一个项目的SECRET_KEY,那么可以使用app.config['SECRET_KEY'] = "xxx"来进行设置,在Flask项目中,有四种方式进行项目的配置:

  1. 直接硬编码:
app = Flask(__name__)
app.config['SECRET_KEY'] = "xxx"
  1. 因为app.configflask.config.Config的实例,而Config类是继承自dict,因此可以通过update方法:
app.config.update(
   DEBUG=True,
   SECRET_KEY='...'
)
  1. 如果你的配置项特别多,你可以把所有的配置项都放在一个模块中,然后通过加载模块的方式进行配置,假设有一个settings.py模块,专门用来存储配置项的,此时你可以通过app.config.from_object()方法进行加载,并且该方法既可以接收模块的的字符串名称,也可以模块对象:
# 1. 通过模块字符串
app.config.from_object('settings')
# 2. 通过模块对象
import settings
app.config.from_object(settings)
  1. 也可以通过另外一个方法加载,该方法就是app.config.from_pyfile(),该方法传入一个文件名,通常是以.py结尾的文件,但也不限于只使用.py后缀的文件:
app.config.from_pyfile('settings.py',silent=True)
# silent=True表示如果配置文件不存在的时候不抛出异常默认是为False会抛出异常。

3. URL与视图

3.1 URL与函数的映射

从之前的helloworld.py文件中,我们已经看到,一个URL要与执行函数进行映射,使用的是@app.route装饰器。@app.route装饰器中,可以指定URL的规则来进行更加详细的映射,比如现在要映射一个文章详情的URL,文章详情的URL/article/id/id有可能为1、2、3…,那么可以通过以下方式:

@app.route('/article/<id>/')
def article(id):
   return '%s article detail' % id

其中<id>,尖括号是固定写法,语法为<variable>variable默认的数据类型是字符串。如果需要指定类型,则要写成<converter:variable>,其中converter就是类型名称,可以有以下几种:

  • string: 默认的数据类型,接受没有任何斜杠/的字符串。
  • int: 整形
  • float: 浮点型。
  • pathstring类似,但是可以传递斜杠/
  • uuid uuid类型的字符串。
  • any可以指定多种路径这个通过一个例子来进行说明:
@app.route('/<any(article,blog):url_path>/')
def item(url_path):
  return url_path

以上例子中,item这个函数可以接受两个URL,一个是/article/,另一个是/blog/。并且,一定要传url_path参数,当然这个url_path的名称可以随便。

如果不想定制子路径来传递参数,也可以通过传统的?=的形式来传递参数,例如:/article?id=xxx,这种情况下,可以通过request.args.get('id')来获取id的值。如果是post方法,则可以通过request.form.get('id')来进行获取。

3.2 构造URLurl_for

一般我们通过一个URL就可以执行到某一个函数。如果反过来,我们知道一个函数,怎么去获得这个URL呢?url_for函数就可以帮我们实现这个功能。url_for()函数接收两个及以上的参数,他接收函数名作为第一个参数,接收对应URL规则的命名参数,如果还出现其他的参数,则会添加到URL的后面作为查询参数

通过构建URL的方式而选择直接在代码中拼URL的原因有两点:

  1. 将来如果修改了URL,但没有修改该URL对应的函数名,就不用到处去替换URL了。
  2. url_for()函数会转义一些特殊字符和unicode字符串,这些事情url_for会自动的帮我们搞定。

下面用一个例子来进行解释:

from flask import Flask,url_for
app = Flask(__name__)

@app.route('/article/<id>/')
def article(id):
    return '%s article detail' % id

@app.route('/')
def index(request):
    print(url_for("article",id=1))
    return "首页"

在访问index的时候会打印出/article/1/

3.3 指定URL末尾的斜杠

有些URL的末尾是有斜杠的,有些URL末尾是没有斜杠的。这其实是两个不同的URL

举个例子:

 @app.route('/article/')
 def articles():
     return '文章列表页'

上述例子中,当访问一个结尾不带斜线的URL/article,会被重定向到带斜线的URL/article/上去。但是当我们在定义articleurl的时候,如果在末尾没有加上斜杠,但是在访问的时候又加上了斜杠,这时候就会抛出一个404错误页面了:

@app.route("/article")
def articles(request):
    return "文章列表页面"

以上没有在末尾加斜杠,因此在访问/article/的时候,就会抛出一个404错误。

3.4 指定HTTP方法

@app.route()中可以传入一个关键字参数methods来指定本方法支持的HTTP方法,默认情况下,只能使用GET请求,看以下例子:

@app.route('/login/',methods=['GET','POST'])
def login():
    return 'login'

以上装饰器将让loginURL既能支持GET又能支持POST

3.5 页面跳转和重定向

重定向分为永久性重定向和暂时性重定向,在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此我们应该给他重定向到登录页面。

  • 永久性重定向:http的状态码是301,多用于旧网址被废弃了要转到一个新的网址确保用户的访问,最经典的就是京东网站,你输入www.jingdong.com的时候,会被重定向到www.jd.com,因为jingdong.com这个网址已经被废弃了,被改成jd.com,所以这种情况下应该用永久重定向。
  • 暂时性重定向:http的状态码是302,表示页面的暂时性跳转。比如访问一个需要权限的网址,如果当前用户没有登录,应该重定向到登录页面,这种情况下,应该用暂时性重定向。

flask中,重定向是通过flask.redirect(location,code=302)这个函数来实现的,location表示需要重定向到的URL,应该配合之前讲的url_for()函数来使用,code表示采用哪个重定向,默认是302也即暂时性重定向,可以修改成301来实现永久性重定向。

以下来看一个例子,关于在flask中怎么使用重定向:

 from flask import Flask,url_for,redirect

 app = Flask(__name__)
 app.debug = True

 @app.route('/login/',methods=['GET','POST'])
 def login():
     return 'login page'

 @app.route('/profile/',methods=['GET','POST'])
 def profile():
     name = request.args.get('name')

     if not name:
     # 如果没有name说明没有登录重定向到登录页面
         return redirect(url_for('login'))
     else:
         return name