【后端开发】Flask学习教程

目录

一、Flask 是什么?

二、环境搭建,准备启航

2.1 安装 Python

2.2 安装 Flask 库

三、第一个 Flask 程序,初窥门径

3.1 导入 Flask 类

3.2 创建应用实例

3.3 定义路由和视图函数

3.4 运行应用

四、深入理解 Flask 核心概念

4.1 路由系统详解

4.2 请求与响应处理

4.3 模板引擎 Jinja2

五、Flask 扩展,增强战斗力

5.1 Flask - SQLAlchemy:数据库操作的得力助手

5.2 Flask - WTF:表单处理的便捷工具

六、实战项目:打造简易博客

6.1 项目需求分析

6.2 数据库设计

6.3 功能实现

6.3.1 文章展示

6.3.2 文章发布

6.3.3 用户管理

七、部署上线,让世界看见

7.1 选择服务器

7.2 安装依赖

7.3 配置 Web 服务器(以 Nginx 为例)

7.4 启动应用

八、总结与展望


一、Flask 是什么?

在当今的 Web 开发领域,各种框架层出不穷,Flask 便是其中备受瞩目的一颗新星,它是一个使用 Python 编写的轻量级 Web 应用框架,被称为 “microframework”。说它是微框架,并不是说它功能弱,而是它保持了极简的核心,就像一个精巧的工具箱,只提供了 Web 开发最基础的工具和组件 ,把更多选择的自由交给开发者。

Flask 的设计哲学是 “简单优先、灵活性强”,这使得开发者对应用的构建过程有更多的控制权。它不会像一些大型框架那样,强制你使用特定的数据库、窗体验证工具等,而是让你根据项目的实际需求自由选择合适的扩展。比如,如果你需要数据库支持,既可以选择 SQLAlchemy 这样强大的数据库抽象层库,也可以根据具体场景选择其他更适合的库;如果需要表单验证,Flask-WTF 扩展能帮你轻松实现。

Flask 基于两个核心工具库:Werkzeug 和 Jinja2。Werkzeug 是一个 WSGI(Web Server Gateway Interface)工具包,负责处理 HTTP 请求和响应,就像是 Web 应用和服务器之间的 “翻译官”,让两者能够顺畅沟通;Jinja2 则是一个灵活的模板引擎,用于生成动态 HTML 页面,它就像一个精巧的模具,可以根据你的数据生成各式各样的页面。正是这两个强大的工具库,为 Flask 的高效开发奠定了坚实的基础。

也正是这些特点,让 Flask 在 Web 开发中占据了独特的地位,无论是小型项目的快速迭代,还是大型项目的核心模块构建,Flask 都能游刃有余。接下来,就让我们一起深入 Flask 的世界,看看如何用它构建出精彩的 Web 应用吧!

二、环境搭建,准备启航

在正式开启 Flask 学习之旅前,我们得先搭建好开发环境,就好比盖房子要先准备好工具和材料一样。

2.1 安装 Python

Flask 是基于 Python 开发的,所以 Python 是我们的首要安装目标。Python 有众多版本,目前 Python 3 是主流发展方向,并且 Flask 需要 Python 3.6 及以上版本 ,建议大家安装最新的稳定版本。

前往 Python 官网(https://www.python.org/downloads/ ),根据你的操作系统(Windows、macOS 或 Linux )选择对应的安装包。以 Windows 系统为例,下载完成后,双击安装包进行安装。在安装过程中,务必勾选 “Add Python to PATH” 选项,这一步非常关键,它能让我们在命令行中直接使用 Python 命令,就像给 Python 在系统里 “留了个门”,方便我们随时调用。安装完成后,打开命令行窗口(Windows 系统可通过快捷键 Windows+R,输入 “cmd” 打开;macOS 和 Linux 系统可直接打开终端 ),输入 “python --version”,如果显示 Python 的版本号,那就说明安装成功啦!

2.2 安装 Flask 库

安装好 Python 后,接下来要安装 Flask 库。Python 有个强大的包管理器 pip,我们就用它来安装 Flask 。同样在命令行中操作,输入 “pip install Flask”,pip 就会自动从 Python Package Index(PyPI)上下载并安装 Flask 及其依赖项。安装过程可能会持续一会儿,取决于你的网络速度,安装完成后,若想确认是否安装成功,可以输入 “pip show Flask”,如果能看到 Flask 的相关信息,如版本号、作者、安装位置等,就证明 Flask 已经成功入驻你的开发环境啦!

此外,为了更好地管理项目依赖,避免不同项目之间的包冲突,强烈建议大家使用虚拟环境。虚拟环境就像是一个独立的小空间,每个项目都可以有自己专属的虚拟环境,里面安装的包互不干扰。创建虚拟环境也很简单,在命令行中输入 “python -m venv myenv”(“myenv” 是你给虚拟环境取的名字,可自行替换 ),这样就会在当前目录下创建一个名为 “myenv” 的虚拟环境。激活虚拟环境的方式因系统而异,Windows 系统在虚拟环境目录下的 Scripts 文件夹中,执行 “activate” 命令;macOS 和 Linux 系统则在虚拟环境目录下的 bin 文件夹中,执行 “source activate” 命令。激活后,命令行的提示符前面会显示虚拟环境的名字,这就表示你已经进入虚拟环境啦,此时再安装 Flask,就只会安装在这个虚拟环境中,不会影响系统全局的 Python 环境 。

完成以上步骤,你的 Flask 开发环境就搭建好啦,是不是很有成就感?接下来,就让我们正式开始编写 Flask 应用,看看这个强大的框架能创造出怎样的精彩!

三、第一个 Flask 程序,初窥门径

现在,我们已经搭建好了 Flask 开发环境,是不是迫不及待地想看看 Flask 到底怎么用了?别着急,接下来就让我们创建第一个 Flask 应用,迈出探索 Flask 世界的第一步。

3.1 导入 Flask 类

在 Python 中,使用 Flask 前需要先从flask库中导入Flask类,这就像是打开一个工具盒,拿出我们要用的工具。新建一个 Python 文件,比如命名为app.py ,在文件开头输入以下代码:

 

from flask import Flask

这行代码告诉 Python,我们要使用flask库中的Flask类来创建 Web 应用。

3.2 创建应用实例

导入Flask类后,接下来就要创建一个 Flask 应用实例,它就像是我们 Web 应用的 “大脑”,负责协调处理各种请求。在app.py中继续输入以下代码:

 

app = Flask(__name__)

这里的__name__是 Python 的一个内置变量,它表示当前模块的名称。当我们直接运行这个 Python 文件时,__name__的值就是'__main__';当这个文件被作为模块导入到其他文件中时,__name__的值就是这个文件的模块名。Flask 使用__name__来确定应用的根路径,以便正确加载资源,比如模板文件和静态文件。

3.3 定义路由和视图函数

有了应用实例后,我们还需要告诉它,当接收到不同的 URL 请求时,应该执行哪些操作。这就需要定义路由和视图函数了。路由就像是 Web 应用中的 “地图”,它将 URL 映射到对应的视图函数;而视图函数则是处理请求并返回响应的地方,就像是一个个 “小助手”,根据请求的不同给出相应的回答。

在app.py中添加如下代码:

 

@app.route('/')

def hello_world():

return 'Hello, Flask!'

这里使用了app.route装饰器来定义路由,'/'表示根 URL,也就是说,当用户访问我们应用的根路径(例如http://127.0.0.1:5000/ )时,就会触发hello_world这个视图函数。hello_world函数非常简单,它只是返回一个字符串'Hello, Flask!',这个字符串就是服务器返回给客户端(通常是浏览器)的响应内容。

3.4 运行应用

定义好路由和视图函数后,我们的第一个 Flask 应用就基本完成了,接下来就是运行它,看看效果如何。在app.py文件的末尾添加以下代码:

 

if __name__ == '__main__':

app.run()

这段代码的作用是确保只有在直接运行app.py这个文件时,才会启动 Flask 应用。app.run()会启动一个本地开发服务器,默认监听在127.0.0.1:5000地址上,也就是我们通常所说的本地回环地址,端口号为 5000 。这意味着,只有在你自己的计算机上通过浏览器访问http://127.0.0.1:5000/,才能看到应用的运行结果。

现在,保存app.py文件,打开命令行窗口,切换到app.py所在的目录,然后输入python app.py ,如果一切顺利,你会看到命令行中输出一些信息,类似于下面这样:

 

* Serving Flask app 'app'

* Debug mode: off

WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.

* Running on http://127.0.0.1:5000

Press CTRL+C to quit

这表示你的 Flask 应用已经成功启动,正在监听http://127.0.0.1:5000这个地址。打开浏览器,输入http://127.0.0.1:5000/,如果页面上显示出Hello, Flask!,那就恭喜你,成功创建并运行了第一个 Flask 应用!这虽然只是一个简单的示例,但它包含了 Flask 应用开发的基本流程,接下来,我们就可以在这个基础上,不断添加新的功能,让我们的应用变得更加丰富和强大。

四、深入理解 Flask 核心概念

在初步了解 Flask 并创建了第一个简单应用后,我们已经迈出了学习 Flask 的第一步。接下来,让我们深入探索 Flask 的核心概念,这些概念是构建复杂 Flask 应用的基石,掌握它们,你就能更加灵活地运用 Flask 进行 Web 开发。

4.1 路由系统详解

Flask 的路由系统是其一大核心特性,它负责将不同的 URL 请求映射到相应的视图函数上,就像是一个智能的导航仪,根据用户输入的 URL,精准地找到对应的处理程序。

在 Flask 中,定义路由非常简单,使用@app.route装饰器即可。例如,我们之前定义的根路由:

 

@app.route('/')

def hello_world():

return 'Hello, Flask!'

这里的'/'就是根 URL,当用户访问http://127.0.0.1:5000/时,就会触发hello_world视图函数,返回'Hello, Flask!'。这就是最简单的静态路由,URL 和视图函数之间是固定的映射关系。

除了静态路由,Flask 还支持动态路由,它允许我们在 URL 中传递参数,使同一个视图函数可以处理不同参数的请求。比如,我们想要创建一个根据用户名显示欢迎信息的页面,可以这样定义路由:

 

@app.route('/user/<username>')

def greet_user(username):

return f'Hello, {username}!'

在这个例子中,<username>就是一个动态参数,它可以是任意字符串。当用户访问http://127.0.0.1:5000/user/Alice时,Alice就会作为参数传递给greet_user视图函数,函数返回'Hello, Alice!'。这样,通过动态路由,我们可以用一个视图函数处理不同用户的请求,大大提高了代码的复用性。

有时候,我们可能需要对动态参数的类型进行限制,Flask 提供了多种类型转换器来满足这个需求。比如,int类型转换器可以确保参数是整数,float类型转换器用于确保参数是浮点数,path类型转换器可以匹配包含斜杠的路径。示例如下:

 

@app.route('/user/<int:user_id>')

def show_user_profile(user_id):

return f'User ID: {user_id}'

@app.route('/files/<path:filename>')

def serve_file(filename):

return f'Serving file: {filename}'

在/user/<int:user_id>路由中,只有当 URL 中的参数是整数时,才会匹配这个路由,否则会返回 404 错误。而/files/<path:filename>路由可以匹配像/files/images/logo.png这样包含斜杠的文件路径,方便我们处理文件相关的请求。

掌握了 Flask 的路由系统,我们就能根据不同的业务需求,灵活地设计 URL 结构,让 Web 应用的交互更加清晰和高效。

4.2 请求与响应处理

在 Web 开发中,处理 HTTP 请求和生成响应是最核心的任务之一,Flask 提供了简洁而强大的方式来完成这些工作。

当客户端(通常是浏览器)向服务器发送 HTTP 请求时,Flask 会接收到这个请求,并根据路由系统找到对应的视图函数来处理它。在视图函数中,我们可以通过request对象获取请求的各种信息,比如请求方法(GET、POST 等)、请求参数、请求头信息等。

request对象是 Flask 从werkzeug.wrappers模块中导入的Request类的实例,它包含了许多有用的属性和方法。例如,要获取 URL 中的查询参数,可以使用request.args.get('param_name'),其中param_name是参数的名称;如果是 POST 请求,想要获取表单数据,则可以使用request.form.get('field_name')。示例代码如下:

 

from flask import Flask, request

app = Flask(__name__)

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

def login():

if request.method == 'POST':

username = request.form.get('username')

password = request.form.get('password')

# 这里进行登录验证逻辑

if username == 'admin' and password == '123456':

return 'Login successful!'

else:

return 'Login failed. Please check your username and password.'

else:

return '''

<form method="post">

<label for="username">Username:</label>

<input type="text" id="username" name="username" required><br>

<label for="password">Password:</label>

<input type="password" id="password" name="password" required><br>

<input type="submit" value="Login">

</form>

'''

在这个login视图函数中,首先通过request.method判断请求方法是否为 POST,如果是,则从request.form中获取username和password字段进行登录验证;如果是 GET 请求,则返回一个包含登录表单的 HTML 页面。

处理完请求后,视图函数需要返回响应给客户端。在 Flask 中,视图函数的返回值就是响应内容。返回值可以是简单的字符串,Flask 会将其作为文本响应返回;也可以返回一个元组,元组中可以包含响应内容、状态码和响应头信息,例如return 'Response body', 200, {'Content-Type': 'text/plain'};还可以返回一个Response对象,通过Response对象可以更灵活地设置响应的各种属性,如内容类型、编码、Cookie 等。比如,要返回 JSON 格式的数据,可以使用jsonify函数,它会将 Python 字典转换为 JSON 格式的响应,并设置正确的Content-Type头信息:

 

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/data')

def get_data():

data = {'name': 'John', 'age': 30}

return jsonify(data)

通过这样的方式,Flask 让我们能够轻松地处理各种类型的 HTTP 请求,并生成符合需求的响应,为 Web 应用的交互提供了坚实的支持。

4.3 模板引擎 Jinja2

在 Web 开发中,我们常常需要生成动态的 HTML 页面,根据不同的用户请求或数据展示不同的内容。Flask 使用 Jinja2 作为模板引擎,帮助我们实现这一功能。Jinja2 是一个功能强大且灵活的模板引擎,它允许我们在 HTML 模板中嵌入 Python-like 的语法,通过变量替换、控制结构等方式,生成动态的页面内容。

使用 Jinja2 模板引擎,首先需要在 Flask 应用中创建模板文件。模板文件通常以.html为后缀,存放在项目根目录下的templates文件夹中(Flask 会默认在这个文件夹中查找模板文件)。例如,我们创建一个简单的模板文件index.html:

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Welcome</title>

</head>

<body>

<h1>Welcome, {{ name }}!</h1>

<p>Here is a list of items:</p>

<ul>

{% for item in items %}

<li>{{ item }}</li>

{% endfor %}

</ul>

</body>

</html>

在这个模板中,{{ name }}是一个变量占位符,它会在模板渲染时被替换为实际的值;{% for item in items %}和{% endfor %}是 Jinja2 的控制结构,用于循环遍历items列表,并将每个元素渲染到页面上。

在 Flask 应用中,使用render_template函数来渲染模板。render_template函数的第一个参数是模板文件名,后面可以跟多个键值对,用于传递变量给模板。示例代码如下:

 

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')

def index():

name = 'Alice'

items = ['apple', 'banana', 'cherry']

return render_template('index.html', name=name, items=items)

在这个index视图函数中,定义了name和items两个变量,并通过render_template函数将它们传递给index.html模板。当用户访问根路径时,模板会被渲染,{{ name }}会被替换为Alice,{% for item in items %}循环会将items列表中的元素依次渲染到页面上,最终生成包含动态内容的 HTML 页面返回给客户端。

Jinja2 还支持条件判断、宏定义、模板继承等高级特性。比如,使用条件判断可以根据不同的条件显示不同的内容:

 

{% if user.is_authenticated %}

<p>Welcome, {{ user.username }}!</p>

{% else %}

<p>Please log in.</p>

{% endif %}

模板继承则允许我们创建一个基础模板,其他模板可以继承这个基础模板,并覆盖或扩展其中的部分内容,提高代码的复用性。例如,创建一个基础模板base.html:

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>{% block title %}Default Title{% endblock %}</title>

</head>

<body>

{% block content %}

{% endblock %}

</body>

</html>

然后创建一个子模板home.html继承自base.html:

 

{% extends 'base.html' %}

{% block title %}Home Page{% endblock %}

{% block content %}

<h1>Welcome to the Home Page!</h1>

<p>This is the content of the home page.</p>

{% endblock %}

在home.html中,使用{% extends 'base.html' %}声明继承自base.html,然后通过{% block title %}和{% block content %}覆盖base.html中相应块的内容,生成个性化的页面。

通过 Jinja2 模板引擎,我们能够将业务逻辑和页面展示分离,使代码结构更加清晰,同时方便地生成各种动态页面,为用户提供丰富的交互体验。

五、Flask 扩展,增强战斗力

随着项目规模的不断扩大和业务需求的日益复杂,仅依靠 Flask 本身的核心功能可能无法满足所有需求。这时,Flask 丰富的扩展库就派上用场了,它们就像是给 Flask 装上了各种强大的 “武器”,让其战斗力大幅提升。下面为大家介绍一些常用的 Flask 扩展。

5.1 Flask - SQLAlchemy:数据库操作的得力助手

在 Web 应用开发中,数据库是存储和管理数据的关键组件。Flask - SQLAlchemy 是 Flask 与 SQLAlchemy 的完美结合,它为 Flask 应用提供了便捷的数据库操作方式,让我们可以使用面向对象的方式来操作数据库,而无需编写大量繁琐的 SQL 语句。

SQLAlchemy 是 Python 中一个强大的数据库抽象层库,它允许我们使用统一的 API 来操作多种不同类型的数据库,如 MySQL、PostgreSQL、SQLite 等。Flask - SQLAlchemy 则进一步简化了在 Flask 应用中使用 SQLAlchemy 的过程,提供了更简洁的配置和使用方法。

使用 Flask - SQLAlchemy,我们可以轻松定义数据库模型类,每个类对应数据库中的一个表,类的属性对应表中的列。例如,定义一个简单的用户表:

 

from flask import Flask

from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///test.db'

db = SQLAlchemy(app)

class User(db.Model):

id = db.Column(db.Integer, primary_key=True)

username = db.Column(db.String(80), unique=True, nullable=False)

email = db.Column(db.String(120), unique=True, nullable=False)

def __repr__(self):

return f'<User {self.username}>'

在这个例子中,User类继承自db.Model,id、username和email是定义的列,通过db.Column来指定列的类型和属性,如primary_key=True表示这是主键,unique=True表示该列的值必须唯一,nullable=False表示该列不能为空。

定义好模型类后,就可以使用db.session来进行数据库的增删改查操作了。比如添加一个用户:

 

@app.route('/add_user')

def add_user():

user = User(username='test_user', email='test@example.com')

db.session.add(user)

db.session.commit()

return 'User added!'

通过db.session.add()方法将新用户添加到会话中,再使用db.session.commit()提交会话,将数据真正保存到数据库中。查询用户也非常简单:

 

@app.route('/get_user/<int:user_id>')

def get_user(user_id):

user = User.query.get(user_id)

if user:

return f'User: {user.username}, Email: {user.email}'

else:

return 'User not found'

这里使用User.query.get(user_id)根据用户 ID 查询用户,query是SQLAlchemy提供的查询对象,通过它可以进行各种复杂的查询操作。

Flask - SQLAlchemy 适用于各种需要与关系型数据库交互的 Web 应用场景,无论是小型的个人项目,还是大型的企业级应用,它都能帮助我们高效地管理数据库,专注于业务逻辑的实现。

5.2 Flask - WTF:表单处理的便捷工具

在 Web 应用中,表单是用户与服务器进行交互的重要方式之一,比如用户注册、登录、提交评论等功能都离不开表单。Flask - WTF 是 Flask 与 WTForms 的集成扩展,它极大地简化了在 Flask 应用中处理表单的过程,包括表单的创建、验证、渲染以及 CSRF(跨站请求伪造)保护等功能。

WTForms 是一个灵活且强大的表单验证和处理库,它支持各种常见的表单字段类型,如文本框、密码框、下拉列表、复选框等,并且提供了丰富的验证器,如必填验证、邮箱格式验证、长度验证等。Flask - WTF 在 WTForms 的基础上,进一步整合了 Flask 的上下文和请求处理机制,使得表单处理与 Flask 应用的开发流程更加契合。

以一个简单的用户登录表单为例,使用 Flask - WTF 创建表单类:

 

from flask_wtf import FlaskForm

from wtforms import StringField, PasswordField, SubmitField

from wtforms.validators import DataRequired, Email

class LoginForm(FlaskForm):

username = StringField('Username', validators=[DataRequired()])

password = PasswordField('Password', validators=[DataRequired()])

submit = SubmitField('Login')

在这个表单类中,StringField表示文本输入框,PasswordField表示密码输入框,SubmitField表示提交按钮,validators参数用于指定验证器,DataRequired()表示该字段为必填项。

在视图函数中使用表单:

 

from flask import Flask, render_template, request

app = Flask(__name__)

app.config['SECRET_KEY'] ='some_secret_key' # 用于CSRF保护,必须设置

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

def login():

form = LoginForm()

if form.validate_on_submit():

username = form.username.data

password = form.password.data

# 这里进行登录验证逻辑

if username == 'admin' and password == '123456':

return 'Login successful!'

else:

return 'Login failed. Please check your username and password.'

return render_template('login.html', form=form)

在视图函数中,首先创建表单实例form = LoginForm(),然后通过form.validate_on_submit()验证表单是否提交且数据是否通过验证。如果验证通过,就可以从form对象中获取表单数据进行后续处理。

在模板文件login.html中渲染表单也非常简单:

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Login</title>

</head>

<body>

<form method="post">

{{ form.csrf_token }}

{{ form.username.label }} {{ form.username() }}

{{ form.password.label }} {{ form.password() }}

{{ form.submit() }}

</form>

</body>

</html>

{{ form.csrf_token }}用于生成和验证 CSRF 令牌,保护表单免受跨站请求伪造攻击,其他字段则通过form.field_name.label和form.field_name()分别渲染字段标签和输入框。

Flask - WTF 使得表单处理变得简单、安全且高效,适用于各种需要用户输入和表单交互的 Web 应用场景,帮助我们提升用户体验,确保数据的合法性和安全性。

六、实战项目:打造简易博客

学习编程最好的方式之一就是通过实战项目,接下来,我们就用 Flask 来打造一个简易博客系统。通过这个项目,你将把之前学到的 Flask 知识融会贯通,真正掌握 Flask 在实际项目中的应用。

6.1 项目需求分析

我们要打造的简易博客系统,主要具备以下几个核心功能模块:

  • 文章展示:能够在首页展示博客文章列表,包括文章标题、摘要、发布时间等信息;点击文章标题可进入文章详情页,查看完整的文章内容。
  • 文章发布:博主可以登录系统,在后台撰写新的文章,编辑文章标题、内容,并选择发布。发布后的文章能即时显示在文章列表和详情页中。
  • 用户管理:支持用户注册、登录功能,只有注册并登录的用户才能进行文章发布操作;同时,为了保障用户信息安全,需要对用户密码进行加密存储 。

6.2 数据库设计

为了存储博客相关的数据,我们使用 Flask - SQLAlchemy 来设计数据库。主要涉及两张表:用户表(User)和文章表(Article),它们之间存在一对多的关系,即一个用户可以发布多篇文章。

使用 Flask - SQLAlchemy 定义模型类如下:

 

from flask import Flask

from flask_sqlalchemy import SQLAlchemy

from datetime import datetime

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///blog.db'

db = SQLAlchemy(app)

class User(db.Model):

id = db.Column(db.Integer, primary_key=True)

username = db.Column(db.String(80), unique=True, nullable=False)

password = db.Column(db.String(256), nullable=False)

articles = db.relationship('Article', backref='author', lazy='dynamic')

class Article(db.Model):

id = db.Column(db.Integer, primary_key=True)

title = db.Column(db.String(200), nullable=False)

content = db.Column(db.Text, nullable=False)

publish_time = db.Column(db.DateTime, default=datetime.utcnow)

user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)

在User类中,articles属性通过db.relationship建立了与Article表的关联,backref='author'表示在Article模型中可以通过author属性反向引用对应的User对象;lazy='dynamic'表示在访问articles属性时,不会立即加载数据,而是返回一个查询对象,只有在真正需要数据时才会执行查询,这样可以提高性能 。

在Article类中,user_id是外键,关联到User表的id字段,用于建立用户和文章之间的关系 。

6.3 功能实现

接下来,我们逐步实现博客系统的各项功能。

6.3.1 文章展示
  • 首页文章列表展示:创建一个视图函数,查询所有文章并按发布时间倒序排列,然后通过模板渲染展示在首页。
 

@app.route('/')

def index():

articles = Article.query.order_by(Article.publish_time.desc()).all()

return render_template('index.html', articles=articles)

在index.html模板中,使用 Jinja2 语法循环遍历文章列表并展示相关信息:

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Blog</title>

</head>

<body>

<h1>My Blog</h1>

{% for article in articles %}

<div>

<h2><a href="{{ url_for('article_detail', article_id=article.id) }}">{{ article.title }}</a></h2>

<p>{{ article.content[:100] }}...</p>

<p>Published by {{ article.author.username }} on {{ article.publish_time }}</p>

</div>

{% endfor %}

</body>

</html>

  • 文章详情页展示:根据文章 ID 查询对应的文章,并在详情页展示其完整内容。
 

@app.route('/article/<int:article_id>')

def article_detail(article_id):

article = Article.query.get_or_404(article_id)

return render_template('article_detail.html', article=article)

在article_detail.html模板中展示文章的标题、内容和作者信息:

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>{{ article.title }}</title>

</head>

<body>

<h1>{{ article.title }}</h1>

<p>Published by {{ article.author.username }} on {{ article.publish_time }}</p>

<p>{{ article.content }}</p>

</body>

</html>

6.3.2 文章发布
  • 用户登录验证:使用 Flask - WTF 创建登录表单,验证用户输入的用户名和密码是否正确。
 

from flask_wtf import FlaskForm

from wtforms import StringField, PasswordField, SubmitField

from wtforms.validators import DataRequired

class LoginForm(FlaskForm):

username = StringField('Username', validators=[DataRequired()])

password = PasswordField('Password', validators=[DataRequired()])

submit = SubmitField('Login')

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

def login():

form = LoginForm()

if form.validate_on_submit():

username = form.username.data

password = form.password.data

user = User.query.filter_by(username=username, password=password).first()

if user:

# 这里可以添加登录成功后的逻辑,比如设置session

return redirect(url_for('index'))

else:

return 'Login failed. Please check your username and password.'

return render_template('login.html', form=form)

在login.html模板中渲染登录表单:

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Login</title>

</head>

<body>

<h1>Login</h1>

<form method="post">

{{ form.csrf_token }}

{{ form.username.label }} {{ form.username() }}<br>

{{ form.password.label }} {{ form.password() }}<br>

{{ form.submit() }}

</form>

</body>

</html>

  • 文章发布功能:只有登录用户才能访问文章发布页面,创建文章发布表单,将用户输入的文章信息保存到数据库。
 

from flask_wtf import FlaskForm

from wtforms import StringField, TextAreaField, SubmitField

from wtforms.validators import DataRequired

class ArticleForm(FlaskForm):

title = StringField('Title', validators=[DataRequired()])

content = TextAreaField('Content', validators=[DataRequired()])

submit = SubmitField('Publish')

@app.route('/publish', methods=['GET', 'POST'])

def publish():

# 这里可以添加登录验证逻辑,比如检查session中是否有用户信息

form = ArticleForm()

if form.validate_on_submit():

title = form.title.data

content = form.content.data

user = User.query.first() # 这里简单示例取第一个用户,实际应根据登录用户获取

new_article = Article(title=title, content=content, user=user)

db.session.add(new_article)

db.session.commit()

return redirect(url_for('index'))

return render_template('publish.html', form=form)

在publish.html模板中渲染文章发布表单:

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Publish Article</title>

</head>

<body>

<h1>Publish Article</h1>

<form method="post">

{{ form.csrf_token }}

{{ form.title.label }} {{ form.title() }}<br>

{{ form.content.label }} {{ form.content() }}<br>

{{ form.submit() }}

</form>

</body>

</html>

6.3.3 用户管理
  • 用户注册:创建用户注册表单,验证用户输入的用户名、密码等信息,并将新用户保存到数据库。
 

from flask_wtf import FlaskForm

from wtforms import StringField, PasswordField, SubmitField

from wtforms.validators import DataRequired, EqualTo, Email

class RegisterForm(FlaskForm):

username = StringField('Username', validators=[DataRequired()])

email = StringField('Email', validators=[DataRequired(), Email()])

password = PasswordField('Password', validators=[DataRequired()])

confirm_password = PasswordField('Confirm Password',

validators=[DataRequired(), EqualTo('password')])

submit = SubmitField('Register')

@app.route('/register', methods=['GET', 'POST'])

def register():

form = RegisterForm()

if form.validate_on_submit():

username = form.username.data

email = form.email.data

password = form.password.data

new_user = User(username=username, password=password, email=email)

db.session.add(new_user)

db.session.commit()

return redirect(url_for('login'))

return render_template('register.html', form=form)

在register.html模板中渲染用户注册表单:

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Register</title>

</head>

<body>

<h1>Register</h1>

<form method="post">

{{ form.csrf_token }}

{{ form.username.label }} {{ form.username() }}<br>

{{ form.email.label }} {{ form.email() }}<br>

{{ form.password.label }} {{ form.password() }}<br>

{{ form.confirm_password.label }} {{ form.confirm_password() }}<br>

{{ form.submit() }}

</form>

</body>

</html>

通过以上步骤,我们基本实现了简易博客系统的主要功能。当然,这只是一个基础版本,实际应用中还可以进一步完善,如添加用户权限管理、评论功能、文件上传等,感兴趣的话你可以自己动手尝试拓展 。

七、部署上线,让世界看见

经过前面的学习和实战,我们已经成功开发出了功能丰富的 Flask 应用。现在,是时候让这个精心打造的应用走出本地开发环境,面向更广阔的互联网世界,让更多的人能够访问和使用它。接下来,我们就详细介绍如何将 Flask 应用部署到服务器上。

7.1 选择服务器

选择服务器时,需要综合考虑多个因素。首先是性能,要根据应用的预估访问量和数据处理需求来确定服务器的配置,包括 CPU、内存、硬盘等。例如,如果应用是一个小型的个人博客,访问量相对较低,那么选择 1 核 2G 内存的云服务器可能就足够了;但如果是一个面向大量用户的电商平台,就需要更高配置的服务器来保证运行的流畅性 。

其次是稳定性,选择知名的云服务提供商可以有效保障服务器的稳定性,像阿里云、腾讯云、华为云等,它们都有专业的运维团队和完善的技术支持,能够确保服务器的持续稳定运行 。

成本也是一个重要因素,不同配置和服务提供商的服务器价格差异较大,在满足应用需求的前提下,要尽量选择性价比高的方案。一些云服务提供商还会针对新用户推出优惠活动,比如新用户首购服务器可以享受较低的价格,这对于个人开发者和小型团队来说是一个不错的选择 。

7.2 安装依赖

将 Flask 应用部署到服务器后,首先要安装应用所需的依赖包。如果在开发过程中使用了requirements.txt文件来记录依赖,那么在服务器上部署时就非常方便。通过 SSH 连接到服务器,进入应用所在的目录,然后执行命令pip install -r requirements.txt,pip 就会自动从 PyPI 下载并安装所有依赖包 。

如果没有使用requirements.txt文件,也可以手动安装依赖,例如pip install Flask、pip install Flask - SQLAlchemy等,根据应用实际使用的库进行安装 。为了避免不同项目之间的包冲突,同样建议在服务器上使用虚拟环境,创建和激活虚拟环境的方法与本地开发环境一致 。

7.3 配置 Web 服务器(以 Nginx 为例)

Nginx 是一款高性能的 HTTP 和反向代理服务器,在部署 Flask 应用时,常被用作反向代理服务器,它可以将客户端的请求转发到 Flask 应用程序,并处理一些静态文件的请求,提高应用的性能和安全性 。

首先,在服务器上安装 Nginx。如果是基于 Debian 或 Ubuntu 的系统,可以使用命令sudo apt - get install nginx进行安装;如果是基于 CentOS 的系统,则使用命令sudo yum install nginx 。

安装完成后,需要配置 Nginx 的虚拟主机。在 Nginx 的配置目录(通常是/etc/nginx/sites - available)下创建一个新的配置文件,例如myapp.conf,并添加以下内容:

 

server {

listen 80;

server_name your_domain.com; # 替换为你的域名或服务器IP

location / {

proxy_pass http://127.0.0.1:5000; # Flask应用运行的地址和端口

proxy_set_header Host $host;

proxy_set_header X - Real - IP $remote_addr;

proxy_set_header X - Forwarded - For $proxy_add_x_forwarded_for;

proxy_set_header X - Forwarded - Proto $scheme;

}

}

这段配置的含义是,Nginx 监听 80 端口,当接收到客户端对your_domain.com的请求时,将请求转发到本地的 5000 端口(即 Flask 应用运行的端口)。同时,设置一些请求头信息,以便 Flask 应用能够正确获取客户端的真实 IP 地址等信息 。

配置完成后,需要启用这个虚拟主机配置文件。在终端中执行命令sudo ln -s /etc/nginx/sites - available/myapp.conf /etc/nginx/sites - enabled/,然后重启 Nginx 服务,使配置生效,命令为sudo systemctl restart nginx 。

7.4 启动应用

在服务器上启动 Flask 应用也有多种方式。如果应用比较简单,可以直接使用python app.py命令启动,但这种方式只适用于开发和测试环境,在生产环境中不推荐使用,因为它的性能和稳定性较差 。

在生产环境中,通常使用 WSGI 服务器来启动 Flask 应用。Gunicorn 是一个常用的 WSGI 服务器,安装 Gunicorn 可以使用命令pip install gunicorn 。假设 Flask 应用的入口文件是app.py,应用实例名为app,那么可以使用以下命令启动 Gunicorn:gunicorn -w 4 -b 127.0.0.1:5000 app:app 。其中,-w 4表示启动 4 个工作进程,-b 127.0.0.1:5000表示绑定到本地的 5000 端口,app:app指定了 Flask 应用实例的位置 。

为了确保应用在服务器后台持续运行,即使关闭 SSH 连接也不会停止,可以使用screen或supervisor等工具。以supervisor为例,首先安装supervisor,命令为sudo apt - get install supervisor(Debian 或 Ubuntu 系统)或sudo yum install supervisor(CentOS 系统) 。

安装完成后,在/etc/supervisor/conf.d/目录下创建一个新的配置文件,例如myapp.conf,并添加以下内容:

 

[program:myapp]

command = gunicorn -w 4 -b 127.0.0.1:5000 app:app

directory = /path/to/your/app # 替换为Flask应用所在的目录

autostart = true

autorestart = true

stderr_logfile = /var/log/myapp.err.log

stdout_logfile = /var/log/myapp.out.log

这段配置指定了要运行的命令(即启动 Gunicorn 的命令)、应用所在的目录,以及设置了自动启动和自动重启等选项。配置完成后,执行命令sudo supervisorctl reread和sudo supervisorctl update,使配置生效 。

至此,我们已经完成了将 Flask 应用部署到服务器的全部流程。现在,通过访问服务器的域名或 IP 地址,就可以看到我们精心开发的 Flask 应用在互联网上成功运行啦!在后续的使用过程中,还需要定期监控应用的运行状态,及时处理可能出现的问题,确保应用的稳定运行 。

八、总结与展望

到这里,我们的 Flask 学习之旅就暂告一段落啦!回顾这一路,我们从 Flask 的基本概念入手,了解了它轻量级、灵活性强的特点,以及基于 Werkzeug 和 Jinja2 的核心架构 。接着,我们一步步搭建开发环境,创建了第一个 Flask 应用,体验了从代码到网页展示的奇妙过程 。在深入学习核心概念时,我们掌握了路由系统的灵活运用,学会根据不同的 URL 请求执行相应的视图函数;明白了如何处理 HTTP 请求与响应,获取请求信息并返回合适的响应内容;还领略了 Jinja2 模板引擎的魅力,能够轻松生成动态的 HTML 页面 。

我们还探索了 Flask 扩展的强大功能,借助 Flask - SQLAlchemy 实现了高效的数据库操作,利用 Flask - WTF 简化了表单处理流程 。通过实战项目打造简易博客,我们将所学知识融会贯通,完成了从需求分析、数据库设计到功能实现的全过程,真正感受到了 Flask 在实际项目中的应用价值 。最后,我们成功将 Flask 应用部署上线,让它从本地走向了更广阔的网络世界 。

Flask 的世界丰富多彩,我们所学的只是冰山一角。希望大家在今后的学习和实践中,继续深入探索 Flask 的更多功能和应用场景。比如尝试开发更复杂的 Web 应用,像电商平台、社交网络等;学习使用更多的 Flask 扩展,实现用户权限管理、文件上传下载、邮件发送等功能;还可以结合前端框架,如 Vue.js、React 等,打造出更加美观和交互性强的 Web 应用 。

学习编程是一个不断实践和积累的过程,每一次的尝试和挑战都是成长的机会。相信只要大家保持热情,坚持不懈,一定能在 Flask 开发的道路上越走越远,创造出更多精彩的 Web 应用!如果在学习过程中遇到问题,不要害怕,多查阅文档、参考优秀的开源项目,也可以在技术社区中与其他开发者交流分享,共同进步 。期待大家在 Flask 的世界里收获满满,开启属于自己的技术之旅!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大雨淅淅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值