通过本文,你应该掌握:
- Hello World程序搭建
- 视图函数编写
- HTML页面渲染
- 前后端参数传递
- Jinja模板基础
原文链接
欢迎来我的论坛讨论Flask
搭建博客网站的问题和经验。www.ahoh.club。
本系列所有文章都会同步到这里,如果不想关注博主,就来这里阅读吧!
使用Flask写一个博客系统
写在前面
我是一个毕业于计算机专业,却很遗憾没有进入互联网行业的人。直到我永远的离开了那个千万人唾弃的血汗工厂,才发现原来我一直深爱着这个行业。在工作的这段时间里,我每天都能感受到技能的流失、学业的荒废。
现在只希望能留下点代码,记录曾经七年的光阴,时间能带走我的技能,却不能停掉我的服务器!!
我也是在C、C++、Java各种技能都丢失后,才捡起了Python,在学习过程中,我发现很多教程都非常老旧,也有很精彩的教程断更,既然别人靠不住,那我就自己来!!
我会深耕这个系列,争取把它打造成一个精品教程!
1. 你好,Flask
在编程学习过程中,万物始于Hello World
,我也不例外,在使用Flask
开发Web
应用之前,我想先创建一个Hello World
应用。
首先,给项目起一个有意思的名字,作为一个美好的开始。我现在想命名我的项目为:Ahoh
,也就是啊哦~
,因为我遇到BUG
都会啊哦一下。好吧,先创建项目文件夹并进入目录:
~$ mkdir ahoh # 创建项目文件夹(根目录)
~$ cd ahoh
另外,Python
应用开发往往都是运行在虚拟环境中的,所以我还要Ahoh
运行在虚拟环境中。创建虚拟环境,并激活:
~/ahoh$ python3 -m venv venv # 创建一个名字叫venv的虚拟环境目录
~/ahoh$ . venv/bin/activate # 激活虚拟环境
(venv)~/ahoh$ # 激活成功后,可以看到命令行之前出现了venv字样
既然是写Flask
应用,那安装Flask
包肯定是必不可少的:
(venv)~/ahoh$ pip install -U pip # 更新pip
(venv)~/ahoh$ pip install flask # 安装Flask
OK,现在环境就布置好了,可以开始愉快的敲代码了。
首先,我需要一个Flask
的入口文件,按照官方文档的建议,就起名app.py
:
(venv)~/ahoh$ touch app.py
最简单的Flask
项目,就只需要一个文件,我的Hello World
也是这样。
在 app.py
文件中写入以下代码:
# ~/ahoh/app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '你好, Flask'
你可以选择使用
Vim
,也可以选择VSCode
和PyCharm
等集成开发工具。
到这里为止,整个Hello World
项目就写完了,真是太容易了。
下面就要跑起来我的Hello World
项目,只需要在命令行中输入flask run
:
(venv)~/ahoh$ flask run # 启动Flask应用
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
如果输出和上面一样,很有可能就是成功了,这个时候,只需要在浏览器中输入127.0.0.1:5000
就能访问网站了!
你的结果和我一样吗?为了写这个小项目,我还专门搭建了项目论坛:www.ahoh.club ,欢迎来访!(这不是广告,里面只有我一个人,哈哈哈)
2. 你好,HTML
上小节中,我已经成功让Hello World
项目输出了你好,Flask
,但这绝不是我最终的要求。
我想要的必然是花里胡哨的网页,也就是HTML
页面。
既然需要HTML
,那就直接写个HTML
代码,并通过/html
访问新的HTML
页面,在app.py
中追加代码如下:
# ~/ahoh/app.py
@app.route('/html')
def html():
html_str = """
<html>
<head>
<title>HTML页面</title>
</head>
<body>
<h1>我的第一个HTML页面</h1>
<hr>
<p> Oh,我的老天爷啊,这真是一个了不得的项目,我向上帝保证这是真的。 </p>
</body>
</html>
"""
return html_str
然后,使用flask run
命令重新启动Ahoh
项目,在浏览器中输入127.0.0.1/html
,就可以看到一个简单的HTML
页面了!
虽然已经可以看到了HTML
页面,还存在一个严重的问题:哪个小傻瓜还会在业务代码里面写HTML
呢?
常规情况下,HTML
都是存储在.html
文件中的,和业务代码隔离,还好Flask
早就想好处理方式。
在Flask
中,所有的HTML
文件默认存储在templates
文件夹下,所以,需要先创建templates
文件夹,然后在文件夹内创建HTML
文件,这里我就创建一个hello.html
文件。
(venv)~/ahoh$ mkdir templates # 创建templates文件夹
(venv)~/ahoh$ touch templates/hello.html # 创建html文件
然后将上面例子中html_str
中的值复制到hello.html
文件中,然后稍作修改,如下:
<!-- ~/ahoh/templates/hello.html -->
<html>
<head>
<title>HTML页面</title>
</head>
<body>
<h1>我的第二个HTML页面</h1>
<hr>
<p> How Are You, Savior </p>
</body>
</html>
首先,在app.py
文件的头部引入render_template
函数:
from flask import render_template
然后,在app.py
中追加新的路由函数,访问路径就定为/hello
:
# ~/ahoh/app.py
@app.route('/hello')
def hello():
return render_template('hello.html')
这样,就完成了hello.html
文件的添加,此时,使用flask run
重启服务,在浏览器中输入地址127.0.0.1:5000/hello
就能看到第二个HTML
页面了!
这里,我们使用了一个新的函数
render_template()
,这个函数可以直接渲染HTML
文件,不需要我们从文件中读出HTML
代码后再返回,后面我们使用的Jinja
模板也需要通过这个函数渲染。
3. 你好,Jinja
截至小节2
,我们已经可以成功的利用Flask
返回一个HTML
页面了。
但是,当前的页面只是一个静态的HTML
,文件中的内容都是写死了的,这当然不是我想要的结果。
这里就要引入Flask
默认的HTML
模板引擎Jinja
。
在templates
文件夹中,新建jinja.html
文件,然后将hello.html
中的内容复制过去,并稍作更改。
如下:
<!-- ~/ahoh/templates/jinja.html -->
<html>
<head>
<title>Jinja页面</title>
</head>
<body>
<h1>我的第一个Jinja页面</h1>
<hr>
<p> How Are You, {{name}}</p> <!-- Jinja 使用 {{}} 作为变量 -->
</body>
</html>
然后,在app.py
中新建一个路由函数(视图函数),即追加如下代码:
# ~/ahoh/app.py
@app.route('/jinja')
def jinja():
return render_template('jinja.html',name='Jinja') # 使用name='Jinja'向HTML中传入值
这里,我们就成功的创建了一个动态的页面,在视图函数中,修改
name
的值,前端HTML
就会做出相应的变化。
而name
的值,从后端(视图中)传递到前端(HTML
页面中)也非常的简单,只需要在render_templates()
函数中增加一个参数就可以了。
到这里就结束了吗?当然,没有,我们虽然创建了一个使用Jinja
的HTML
页面,也实现了从后端向前端传递参数,可以动态的修改页面,但是,如何从前端向后端传递参数呢?
在templates
文件夹中创建文件新的HTML
页面,命名为:para.html
,然后将jinja.html
中的内容复制过去,并稍作修改,如下:
<!-- ~/ahoh/templates/para.html -->
<html>
<head>
<title>参数传递</title>
</head>
<body>
<h1>传递参数页面</h1>
<hr>
<p> How Are You, {{name}}</p>
</body>
</html>
然后在app.py
中创建一个新的视图函数,在app.py
文件中追加如下内容:
# ~/ahoh/app.py
@app.route('/para')
@app.route('/para/<string:name>')
def para(name='God'):
return render_template('para.html',name=name)
现在,就可以重启Ahoh
应用,然后在浏览器地址栏中输入127.0.0.1:5000/para/老天爷
,效果如下:
这种传递参数的方式是通过
URL
路径传递,可能大多数人更熟悉的是使用?para_name=value
的方式,在Flask
中同样是可以用的,不过需要在视图函数中使用request.args.get('para_name')
的方式获取传递的值。
感兴趣的童鞋赶快去试试吧,不会做可以留言讨论呦。
4. 你好,templates
最后,也是本文的重点内容,疲倦的同志提提神了!Jinja
模板的引入。
经过第3
小节的学习,相信童鞋们都已经非常清楚,如何添加一个HTML
页面,并创建对应的视图函数了。
但是,有一个问题,当我创建一个HTML
页面的时候,都要完整的在文件中写入一个页面的代码。
而这些代码,大部分情况下都是重复的。
通常情况下,一个页面的HTML
代码是非常长的,如果每次建立新的页面会非常浪费时间。
我希望有一种类似于类继承的机制,可以避免重复代码的出现,这就是Jinja
的模板机制。
首先,我需要先创建一个基础模板,类似于Python
或者Java
的基类。
在templates
文件夹下,创建文件base.html
,内容如下:
<!-- ~/ahoh/templates/base.html -->
<html>
<head>
<!-- Jinja使用{% %}定义代码块 -->
{% block head %}
<title>{{title}}</title>
{% endblock %}
</head>
<body>
{% block header %}
<h1>{{header}}</h1>
{% endblock %}
<hr>
{% block content %}
<p> I want to be a good man. </p>
{% endblock %}
</body>
</html>
此时,基础模板文件就搭建好了。
这个时候,我就想新建一个用于展示文章的页面,post.html
。
首先,在template
文件夹下创建文件post.html
,然后编辑文件如下:
<!-- ~/ahoh/templates/post.html -->
{% extends 'base.html' %}
<!-- head块不在当前页面展示,表示默认继承 -->
<!-- header块显式引用,表示覆盖原有代码,由于这里什么都没写,就是空的 -->
{% block header %}
{% endblock %}
<!-- content同样是显式引用,但是使用了super关键字,表示在继承原有内容的继承上添加。 -->
{% block content %}
{{super()}}
<p> I became a bad guy. </p>
{% endblock %}
然后,在app.py
中添加/template
视图,代码如下:
@app.route('/template')
def template():
return render_template('post.html',title="Template")
重启服务器,后在地址栏输入127.0.0.1:5000/template
,执行结果如下:
虽然,
base.html
非常简单,但是在post.html
中同样展示了Jinja
代码块的三种使用方法,即默认继承使用(head块
)、覆盖(header块
)、最后是继承继承上添加(content块
)。
写在最后
本文重点是Jinja
模板引擎,除了当前展示的简单用法之外,Jinja
还有非常多方便、快捷的使用技巧。
在后继的文中都会一一展示的。
另外,说说本文的写作思路,本系列的文章将采用不求甚解、以功能实现为导向的介绍方法。
这么做的原因是,Flask
全栈技术中的分支过于庞大,一一解读过于复杂。
本文,包括后继的文章,都以实现功能为目的,仅仅介绍需要使用的到的内容,不对技术栈横向发展。
但是,如果文中有讲解的不够清楚的地方,还请留言指正,我会实时更新文档。
此外,欢迎来我的论坛讨论Flask
搭建博客网站的问题和经验。www.ahoh.club。
本系列所有文章都会同步到这里,如果不想关注博主,就来这里阅读吧!