Flask视图和URL
1-虚拟环境
到目前位置,我们所有的第三方包安装都是通过pip install xxx的方式进行安装的,这样安装会将那个包安装到你的系统级的Python环境中。但是这样有应该问题,就是如果你现在用Django 1.10.x写了个网站,然后你的领导跟你说,之前有一个旧项目是用Django 0.9开发的,让你来维护,但是Django 1.10不再兼容Django 0.9的一些语法了。这时候就会碰到一个问题,我如何在我的电脑中同时拥有Django 1.10和Django 0.9两套环境呢?这时候我们就可以通过虚拟环境来解决这个问题。
Windows安装pipenv:pip install pipenv
Mac安装:brew install pipenv
Linux安装:pip install pipenv
pipfile和pipfile.lock
Pipfile文件:
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
flask = "*"
[requires]
python_version = "3.6"
url: # 指国内pip源,不然库会下载很慢
[dev-packages]: # 开发环境
packages: # 生产环境
flask = '*' # '*'号代表使用的是最新版本
[requires] # 代表使用的Python版本
pipfile.lock,详细记录环境依赖,并且利用Hash算法保证了它完整对应关系
如果需要指定Python版本的话,前提是电脑中已经安装Python2和Python3
pipenv --three # 泛指Python3的版本
pipenv -- two # 泛指Python2的版本
pipenv --python 3.7 # 指定Python版本
进入/退出/删除环境环境
pipenv shell # 进入虚拟环境
exit # 退出虚拟环境
pipenv --rm # 删除整个环境 不会删除pipfile
管理开发环境
安装在开发环境下
pipenv install --dev itchat
在虚拟环境中安装包
pienv install 包名
在虚拟环境中允许命令,适应run参数
pipenv run Python manage.py runsever
2-Flask简介
flask是一款非常流行的Python Web框架,出生于2010年,作者是Armin Ronacher,本来这个项目只是作者在愚人节的一个玩笑,后来由于非常受欢迎,进而成为一个正式的项目。flask自2010年发布第一个版本以来,大受欢迎,深得开发者的喜爱,并且在多个公司已经得到了应用,flask能如此流行的原因,可以分为以下几点:
• 微框架、简洁、只做他需要做的,给开发者提供了很大的扩展性。
• Flask和相应的插件写得很好,用起来很爽。
• 开发效率非常高,比如使用SQLAlchemy的ORM操作数据库可以节省开发者大量书写sql的时间
Flask的灵活度非常之高,他不会帮你做太多的决策,一些你都可以按照自己的意愿进行更改。
• 使用Flask开发数据库的时候,具体是使用SQLAlchemy还是MongoEngine,选择权完全掌握在你自己的手中。区别于Django,Django内置了非常完善和丰富的功能,并且如果你想替换成你自己想要的,要么不支持,要么非常麻烦。
• 把默认的Jinija2模板引擎替换成其他模板引擎都是非常容易的。
第一个flask程序
from flask import Flask
app = Flask(__name__)
# app.route是一个装饰器,装饰器映射URL和执行的函数。这个设置将根URL映射到hello_world函数上
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
# 运行本项目
app.run()
3-项目配置
设置DEBUG模式
默认情况下flask不会开启DEBUG模式,开启DEBUG模式后,flask会在每次保存代码的时候自动的重新载入代码,并且如果代码有错误,会在终端进行提示
开启DEBUG模式的三种方法
1.直接在应用对象设置
app.debug = True
app.run()
2.在执行run方法的时候,传递参数进去
app.run(debug=True)
3.在config属性中设置
app.config.update(DEBUG=True)
如果正常会显示如下:
* Restarting with stat
* Debugger is active!
* Debugger PIN: 110-221-148
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
4-URL与视图
1 -URL与函数的映射
从之前的helloword.py文件中,我们已经看到,一个URL要与执行函数进行映射,使用的是@app.route
装饰器。
@app.route
装饰器中,可以指定URL的规则来进行更加详细的映射,比如现在要映射一个文章详情的URL,文章详情的URL是/article/id/,id有可能为1、2、3等,那么可以通过以下方式
from flask import Flask
app = Flask(__name__)
# 装饰器路径
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/demo')
def demo():
return 'demo'
# 指定路径为整型。
@app.route('/demo/<int:aid>/')
def article_list(aid):
return '这是我的第{}文章'.format(aid)
# 指定路径为浮点型
@app.route('/demo/<float:aid>/')
def demo1(aid):
return '这是{}浮点型文章'.format(aid)
# 可以传递有/的斜杠
@app.route('/demo/<path:aid>/')
def article(aid):
return '这是article的第{}文章'.format(aid)
if __name__ == '__main__':
# app.config.update(DEBUG=True)
# app.debug = True
# app.run(debug=True)
app.run()
其中,尖括号是固定写法,语法为,variable默认的数据类型是字符串。如果需要指定类型,则要写成converter:variable
,其中converter就是类型名称,可以有以下几种:
- string: 默认的数据类型,接受没有任何斜杠
/
的字符串 - int: 整型
- float: 浮点型
- path: 和string类似,但是可以传递斜杠/
- uuid: uuid类型的字符串
- any: 可以指定多种路径
如果不想定制子路径来传递参数,也可以通过传统的?=的形式来传递参数,例如:/article?id=xxx
,这种情况下,可以通过requests.args.get('id')
来获取id的值。如果是post方法,则可以通过requests.from.get(‘id’)来进行获取。
2-构造URL(url_for)
一般我们通过一个URL就可以执行到某一个函数。如果反过来,我们知道一个函数,怎么去获取的这个URL呢?url_for函数就可以帮我们实现这个功能。url_for()函数接收两个即以上的参数,它接收函数名作为第一个参数,接收对应URL规则的命名参数,如果还出现其他的参数,则会添加到URL的后面作为查询参数
通过构建URL的方式而选择直接在代码中拼URL的原因有两点
- 将来如果修改了URL,但没有修改该URL对应的函数名,就不用到处去替换URL了。
- url_for()函数会转义一些特殊字符和uniconde字符串,着些事情url_for会自动的帮我们搞定
# -*- coding: utf-8 -*-
# @Time : 2020/4/9 11:20
# @Author : 大数据小J
from flask import Flask, url_for
app = Flask(__name__)
# 装饰器路由
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/article/<int:aid>/')
def article(aid):
# 打印该函数的路由设置
print(url_for('hello_world')) # /
# 当函数中有参数的时候,要设置该函数的参数值,当做路由返回
# 当函数中的参数没有该参数值的时候,路由会将该参数用一个问号连接起来,当一个get请求
# 根据指定的函数名字进行反转,得到函数相对应的路由 重定向
print(url_for('article', aid=10, page=15))
return '这是文章第{}页'.format(aid)
if __name__ == '__main__':
app.debug = True
app.run()
3-指定URL末尾的斜杠
有些URL的末尾是有斜杠的,有些URL末尾是没有斜杆的。
这其实是两种不同的URL
@app.route('/article/')
def articles():
return '文章列表页'
上诉例子中,当访问一个结尾不带斜线的URL:/article
,会被重定向到带斜线的URL:/article/
上去。但是当我们在定义article
的URL的时候,如果在末尾没有加上斜杠,但是在访问的时候又加上了斜杠,这时候就会抛出一个404错误页面
@app.route("/article")
def articles(request):
return "文章列表页面"
以上没有在末尾加斜杆,因此在访问/article/
的时候,就会抛出一个404错误。
4-指定HTTP方法
在app.rount(’/’)中可以传入一个关键字methods指定本方法支持的HTTP方法,默认情况下,只能使用GET
请求
GET请求写法:
request.args.get('接收的key值')
POST请求写法:
request.form.get('接收的key值')
# -*- coding: utf-8 -*-
# @Time : 2020/4/9 11:34
# @Author : 大数据小J
from flask import Flask, request
app = Flask(__name__)
# 默认情况下发送get请求,当要发送其他请求的时候,需要加上methods
@app.route('/login/', methods=['get', 'post'])
def login():
# get发送请求接受数据
get_data = request.args.get('name')
# print(get_data)
# post发送请求接受数据
post_data = request.form.get('class')
# print(request.form.get('age'))
print(post_data)
return 'login'
if __name__ == '__main__':
app.run(debug=True)
5-页面跳转和重定向
重定向分为永久性重定向和暂时性重定向,在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如永华访问一个需要权限的页面,但是该用户当前并没有登录,因此我们应该给他重定向到登录页面
- 永久性重定向:http的状态码是301,多用于旧网址被废弃要转到一个新的网站确保用户的访问。
- 暂时性重定向:http的转台码是302,表示页面的暂时性跳转。比如防卫一个需要权限的网址,如果当前用户没有登录,应该重定向到登录页面,这种情况下,应该用暂时性重定向
在Flask中,重定向是通过flask.redirect('location',code=302)
这个函数来实现的,location
表示需要重定向到的URL,应该配合之前使用过的url_for()
函数来使用,code
表示采用哪个重定向,默认是302也即暂时重定向,可以修改成301来实现用永久重定向
# -*- coding: utf-8 -*-
# @Time : 2020/4/9 13:30
# @Author : 大数据小J
import flask
app = flask.Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
# 登录界面
@app.route('/login/')
def login():
return '这是我的登录界面'
# 这个是请求登录界面
@app.route('/sign_in/')
def sign_in():
name = flask.request.args.get('name')
if name:
return name
else:
# redirect为重定向的一个方法,code为重定向端口号
return flask.redirect(flask.url_for('login'), code=302)
if __name__ == '__main__':
app.run(debug=True)
当访问sign_in
这个页面的时候,当没有name值的时候,会使用redirecr
这个方法进行永久重定向跳转
当传入name值的时候,会返回name对应的value值
5-关于响应(response)
视图函数中可以返回以下类型的值:
-
Response对象
-
字符串。其实Flask是根据返回的字符串类型,重新创建应该
werkzeug.wrappers.Response
对象,Response将该字符串作为主体,状态码为200,MIME类型为text/html
然后返回该Response对象。 -
元组。元组中格式是
(response, status, headers)
。response
为一个字符串,status
值是状态码,headers
是一些响应头。 -
如果表示以上三种类型。那么Flask会通过
Response.force_type(rv,request.environ)
转换一个请求对象。
# -*- coding: utf-8 -*-
# @Time : 2020/4/9 14:56
# @Author : 大数据小J
from flask import Flask, Response, make_response
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello_world'
# 返回的数据类型可以为字符串,字典,元组(元组默认返回下标为0的元组)
@app.route('/about/')
def about():
# return '关于我们'
# return {'name': 'SmallJ'}
# return ('Python', 'Java')
# start为状态码,content_type为内容类型,charset为指定类型
# return Response('关于我们', status=200, content_type='text/html;charset=utf-8')
return make_response('关于我们')
if __name__ == '__main__':
app.run(debug=True)