flask是一款非常流行的Python Web框架,出生于2010年,作者是Armin Ronacher,本来这个项目只是作者在愚人节的一个玩笑,后来由于非常受欢迎,进而成为一个正式的项目。
flask自2010年发布第一个版本以来,大受欢迎,深得开发者的喜爱,目前在Github上的Star数已经超过55.5k了,有超Django之趋势。flask能如此流行的原因,可以分为以下几点:
Flask的灵活度非常之高,他不会帮你做太多的决策,一些你都可以按照自己的意愿进行更改。比如:
在终端输入命令 pip install flask 即可安装。
新建项目中框架选择需pycharm专业版才有这功能
在浏览器中输入http://127.0.0.1:5000就能看到hello world了。需要说明一点的是,app.run这种方式只适合于开发,如果在生产环境中,应该使用Gunicorn或者uWSGI来启动。如果是在终端运行的,可以按ctrl+c来让服务停止。
默认情况下flask不会开启DEBUG模式,开启DEBUG模式后,flask会在每次保存代码的时候自动的重新载入代码,此时网页直接刷新就能看到效果,并且如果代码有错误,会在终端进行提示。
需要注意的是,只能在开发环境下开启DEBUG模式,因为DEBUG模式会带来非常大的安全隐患。
Flask项目的配置,都是通过app.config对象来进行配置的。比如要配置一个项目的SECRET_KEY,那么可以使用app.config[‘SECRET_KEY’] = "xxx"来进行设置
常用有这几种方法:
1、在py文件中直接硬编码:
2、将所有配置项写成一个配置文件,然后使用者进行模块导入
Flask项目内置了许多的配置项,所有的内置配置项,可以点这查看~
从之前的helloworld.py文件中,我们已经看到,一个URL要与执行函数进行映射,使用的是@app.route装饰器。@app.route装饰器中,可以指定URL的规则来进行更加详细的映射,比如现在要映射一个文章详情的URL,文章详情的URL是/article/id/,id有可能为1、2、3…,那么可以通过以下方式:
@app.route('/article//' )
def article(id):
return '%s article detail' % id
其中,尖括号是固定写法,语法为,variable默认的数据类型是字符串。如果需要指定类型,则要写成converter:variable,其中converter就是类型名称,可以有以下几种:
@app.route('//' )
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’)来进行获取
一般我们通过一个URL就可以执行到某一个函数。如果反过来,我们知道一个函数,怎么去获得这个URL呢?url_for函数就可以帮我们实现这个功能。url_for()函数接收两个及以上的参数,他接收函数名作为第一个参数,接收对应URL规则的命名参数,如果还出现其他的参数,则会添加到URL的后面作为查询参数。
在@app.route()中可以传入一个关键字参数methods来指定本方法支持的HTTP方法,默认情况下,只能使用GET请求,看以下例子:
以上装饰器将让login的URL既能支持GET又能支持POST。
重定向分为永久性重定向和暂时性重定向,在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此我们应该给他重定向到登录页面。
在flask中,重定向是通过flask.redirect(location,code=302)这个函数来实现的,location表示需要重定向到的URL,应该配合之前讲的url_for()函数来使用,code表示采用哪个重定向,默认是302也即暂时性重定向,可以修改成301来实现永久性重定向。
两个例子都为如果没有登录或者找不到该用户,即给你重定向到首页或者登录页面!
模板是一个web开发必备的模块。因为我们在渲染一个网页的时候,并不是只渲染一个纯文本字符串,而是需要渲染一个有富文本标签的页面。这时候我们就需要使用模板了。在Flask中,配套的模板是Jinja2,Jinja2的作者也是Flask的作者。这个模板非常的强大,并且执行效率高。以下对Jinja2做一个简单介绍!
要渲染一个模板,通过render_template方法即可,以下将用一个简单的例子进行讲解:
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/about/')
def about():
return render_template('about.html')
当访问/about/的时候,about()函数会在当前目录下的templates(默认不建议修改)文件夹下寻找about.html模板文件。如果想更改模板文件地址,应该在创建app的时候,给Flask传递一个关键字参数template_folder,指定具体的路径,再看以下例子:
from flask import Flask,render_template
app = Flask(__name__,template_folder=r'C:\templates')
@app.route('/about/')
def about():
return render_template('about.html')
以上例子将会在C盘的templates文件夹中寻找模板文件。还有最后一点是,如果模板文件中有参数需要传递,应该怎么传呢,我们再来看一个例子:
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/about/')
def about():
# return render_template('about.html',user='zhiliao')
return render_template('about.html',**{'user':'zhiliao'})
以上例子介绍了两种传递参数的方式,因为render_template需要传递的是一个关键字参数,所以第一种方式是顺其自然的。但是当你的模板中要传递的参数过多的时候,把所有参数放在一个函数中显然不是一个好的选择,因此我们使用字典进行包装,并且加两个*号,来转换成关键字参数。
视图函数的主要作用是,处理业务逻辑,返回响应内容
flask是使用jinja2这个模板引擎来渲染模板
使用模板的好处
模板传参
from flask import Flask,render_template
app = Flask(__name__)
student = {
'name': 'zhangsan',
'age':8,
'gender':'男'
}
student_list = [
{'name': 'zhangsan','age':18,'gender':'男'},
{'name': 'lisi','age':68,'gender':'女'},
{'name': 'wangwu','age':16,'gender':'男'}
]
student_dict = {
'a':{'name': 'zhangsan','age':18,'gender':'男'},
'b':{'name': 'lisi','age':28,'gender':'女'},
'c':{'name': 'wangwu','age':19,'gender':'男'}
}
@app.route('/test1')
def test1():
return render_template('01.html', **student) # 为了方便在模板中使用,可以把字典打散
@app.route('/test2')
def test2():
return render_template('02.html', stu_list = student_list)
@app.route('/test3')
def test3():
return render_template('03.html', stu_dict = student_dict)
if __name__ == '__main__':
app.run()
01.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>第一个模板</title>
</head>
<body>
学生姓名:{{ name }}
学生年龄:{% if age >= 18 %}
已经成年
{% else %}
未成年
{% endif %}
学生性别:{{ gender }}
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>第二个模板</title>
</head>
<body>
{{ stu_list }}
<table border="1px">
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
</tr>
{% for stu in stu_list %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ stu.name }}</td> <!-- 由于stu是字典,有三种写法得到key的value-->
{% if stu.age >= 60 %}
<td>已退休</td>
{% elif stu.age >= 18 %}
<td>已成年</td>
{% else %}
<td>未成年</td>
{% endif %}
{# {{ stu.get('age') }} #}
<td>{{ stu['gender'] }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>第三个模板</title>
</head>
<body>
{{ stu_dict }}
<table border="1px">
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
</tr>
{% for stu_key,stu in stu_dict.items() %}
<tr>
<td>{{ loop.index }},key:{{ stu_key }}</td>
<td>{{ stu.name }}</td> <!-- 由于stu是字典,有三种写法得到key的value-->
{% if stu.age >= 60 %}
<td>已退休</td>
{% elif stu.age >= 18 %}
<td>已成年</td>
{% else %}
<td>未成年</td>
{% endif %}
{# {{ stu.get('age') }} #}
<td>{{ stu['gender'] }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
更多参考原文章
过滤器是通过管道符号(|)进行使用的,例如:{{ name|length }},将返回name的长度。过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。Jinja2中内置了许多过滤器,在这里可以看到所有的过滤器,现对一些常用的过滤器进行讲解:
abs(value):返回一个数值的绝对值。 例如:-1|abs。
default(value,default_value,boolean=false):如果当前变量没有值,则会使用参数中的值来代替。name|default(‘xiaotuo’)——如果name不存在,则会使用xiaotuo来替代。boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true。也可以使用or来替换。
escape(value)或e:转义字符,会将<、>等符号转义成HTML中的符号。例如:content|escape或content|e。
first(value):返回一个序列的第一个元素。names|first。
format(value,*arags,**kwargs):格式化字符串。例如以下代码:
{{ "%s" - "%s"|format('Hello?',"Foo!") }}
将输出:Helloo? - Foo!
last(value):返回一个序列的最后一个元素。示例:names|last。
length(value):返回一个序列或者字典的长度。示例:names|length。
join(value,d=u’'):将一个序列用d这个参数的值拼接成字符串。
safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe。
int(value):将值转换为int类型。
float(value):将值转换为float类型。
lower(value):将字符串转换为小写。
upper(value):将字符串转换为小写。
replace(value,old,new): 替换将old替换为new的字符串。
truncate(value,length=255,killwords=False):截取length长度的字符串。
striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。
trim:截取字符串前面和后面的空白字符。
string(value):将变量转换成字符串。
wordcount(s):计算一个长字符串中单词的个数。
也可以自定义过滤器,但是用的不多~
所有的控制语句都是放在{% … %}中,并且有一个语句{% endxxx %}来进行结束,Jinja中常用的控制语句有if/for…in…,现对他们进行讲解:
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no users found</em></li>
{% endfor %}
</ul>
并且Jinja中的for循环还包含以下变量,可以用来获取当前的遍历状态:
测试器主要用来判断一个值是否满足某种类型,并且这种类型一般通过普通的if判断是有很大的挑战的。语法是:if…is…,先来简单的看个例子:
{% if variable is escaped%}
value of variable: {{ escaped }}
{% else %}
variable is not escaped
{% endif %}