从零开始搭建 flask 博客实验(5)
在前几篇教程中,我们已经实现了:
-
博客系统的基础结构与模板。
-
数据库(SQLAlchemy + Flask‑Migrate)支持。
-
用户注册/登录机制。
本篇将聚焦:用户个人资料页(Profile Page)以及“当前用户视图”(User Center)功能的实现。
一、项目结构预览
当前项目大致目录如下:
flask/ ├── app │ ├── forms.py │ ├── __init__.py │ ├── models.py │ ├── routes.py │ └── templates │ ├── base.html │ ├── index.html │ ├── login.html │ ├── register.html │ └── user.html ├── config.py ├── migrations/ │ └── … (迁移脚本文件) ├── question.py (或其他脚本、入口文件)
(摘自教程开头结构)CSDN博客
二、为用户添加“资料页”视图
在 app/routes.py 中添加如下视图函数:
@app.route('/user/<username>') @login_required def user(username): user = User.query.filter_by(username=username).first_or_404() posts = [ {'author': user, 'body': '测试Post #1号'}, {'author': user, 'body': '测试Post #2号'} ] return render_template('user.html', user=user, posts=posts)
说明:
-
URL 包含
<username>,可直接访问某用户的资料页。 -
要求登录后访问(
@login_required)。 -
从数据库查询该用户名所属用户;若不存在则返回 404。
-
这里示范了
posts变量,即该用户发表的文章列表。实际开发中应由模型查询生成。 CSDN博客
三、为资料页创建模板 user.html
在 app/templates/user.html 中:
{% extends "base.html" %} {% block content %} <h1>用户: {{ user.username }}</h1> <hr> {% for post in posts %} <p>{{ post.author.username }} 说: <b>{{ post.body }}</b></p> {% endfor %} {% endblock %}
功能:显示用户的用户名,以及其文章(或类似内容)。从用户访客视角查看某用户的资料页。 CSDN博客
四、修改基类模板 base.html 以支持“当前用户链接”
为了让“登录用户”看到“我的资料”链接,而游客看不到,修改 base.html 的导航部分:
<div>博客 : <a href="{{ url_for('index') }}">首页</a> {% if current_user.is_anonymous %} <a href="{{ url_for('login') }}">登录</a> {% else %} <a href="{{ url_for('user', username=current_user.username) }}">我的资料</a> <a href="{{ url_for('logout') }}">登出</a> {% endif %} </div>
这样:
-
未登录用户只看到“登录”入口。
-
登录用户看到“我的资料 + 登出”链接。
-
current_user是由 Flask‑Login 提供的当前用户代理对象。 CSDN博客
五、完善用户模型以支持资料与文章关系
虽然教程中这一篇主要用于资料页展示,但实际工程中你可能还需要在 models.py 中为 User 模型添加额外字段,比如头像、简介、注册日期等。
示例:
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, index=True) email = db.Column(db.String(120), unique=True, index=True) bio = db.Column(db.String(140)) # 简介 avatar = db.Column(db.String(200)) # 头像URL posts = db.relationship('Post', backref='author', lazy='dynamic') # …已有set_password, check_password 方法…
在真实应用中:
-
你可能会新增
last_seen(最后活动时间)、member_since(注册时间)等字段。 -
若修改模型结构,别忘了运行迁移命令:
flask db migrate -m "add bio and avatar to User" flask db upgrade
六、彩蛋/进阶建议
-
分页显示:当一个用户有很多文章时,不要一次性加载所有,建议使用分页。
-
头像上传与显示:可以集成第三方图像服务(如 Gravatar)或自己实现上传功能。
-
资料编辑页面:除了“查看”,还可以增加“编辑资料”的视图(如
@app.route('/edit_profile', methods=['GET','POST']))。 -
安全考虑:判断当前用户是否有权限访问某些资料、文章列表。
-
用户可见性设置:比如 “公开/私密”文章过滤。
七、总结
本篇教程为你的博客系统新增了一个用户资料页功能:
-
支持通过
/user/<username>路径查看用户详情。 -
在导航中区分登录状态,提升用户体验。
-
为用户模型与展示模板打下基础
---------项目总体结构讲解-------
项目总体结构(概览)
FLASK_TUTORIAL/
│
├── app/ # Flask 应用的主要逻辑都在这里
│ ├── static/ # 静态文件(CSS、JS、图片等)
│ ├── templates/ # 前端模板文件(HTML)
│ ├── __init__.py # 应用工厂 / 初始化代码
│ ├── forms.py # 表单定义(WTForms)
│ ├── models.py # 数据模型定义(SQLAlchemy)
│ └── routes.py # 路由与视图函数
│
├── migrations/ # 数据库迁移文件夹(由 Flask-Migrate 生成)
│
├── venv/ # 虚拟环境(隔离项目依赖)
│
├── config.py # 配置文件(数据库、密钥、调试模式等)
│
└── myblog.py # 应用入口文件(程序启动点)
🏗 app 文件夹(主程序逻辑)
1️⃣ __init__.py
作用:应用初始化与组件注册。
示例内容大致如下:
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrateapp = Flask(__name__)
app.config.from_object(Config)db = SQLAlchemy(app)
migrate = Migrate(app, db)from app import routes, models
👉 这里做了三件事:
-
创建 Flask 应用对象。
-
载入配置(
Config)。 -
初始化数据库(
db)和迁移工具(migrate)。 -
导入
routes和models,以注册路由和数据库模型。
💡 “Flask 与 MySQL 的握手” 就发生在这里 —— SQLAlchemy(app) 会从配置中读取数据库连接信息(SQLALCHEMY_DATABASE_URI),建立连接。
2️⃣ routes.py
作用:定义网站的“路由”与“逻辑”。
比如:
@app.route('/')
@app.route('/index')
def index():return render_template('index.html')
这里就是告诉 Flask:
-
当有人访问
/或/index,返回index.html。 -
如果用户访问
/login,执行登录逻辑。
📚 一般每个路由函数都对应一个网页页面。
3️⃣ models.py
作用:定义数据库模型(ORM 层)。
使用 SQLAlchemy 描述数据库中的表结构,比如:
class User(db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), unique=True, index=True)email = db.Column(db.String(120), unique=True, index=True)password_hash = db.Column(db.String(128))
这就相当于创建了一张 user 表,包含四个字段。
之后可以:
new_user = User(username="zy", email="xxx@xx.com")
db.session.add(new_user)
db.session.commit()
4️⃣ forms.py
作用:定义网页表单(WTForms)。
例如:
class LoginForm(FlaskForm):username = StringField('用户名', validators=[DataRequired()])password = PasswordField('密码', validators=[DataRequired()])submit = SubmitField('登录')
在模板中就可以使用:
<form method="post">{{ form.username.label }} {{ form.username() }}{{ form.password.label }} {{ form.password() }}{{ form.submit() }}
</form>
📬 Flask-WTF 帮你自动处理验证、CSRF 安全、错误提示等。
5️⃣ templates/
作用:存放 HTML 模板文件
使用 Jinja2 模板语法,可以动态渲染变量,比如:
🏠 base.html
网站的通用布局模板(导航栏、页脚等都在这里)。
其他页面都会用:
{% extends "base.html" %} {% block content %} 页面主体内容 {% endblock %}
你截图中就能看到:
-
顶部导航栏
nav -
主体内容
{% block content %} -
底部图片展示
footer-gallery
📄 其他模板文件:
| 文件名 | 作用 |
|---|---|
| index.html | 网站首页,显示欢迎信息、文章列表等 |
| login.html | 登录页面,对应 LoginForm |
| register.html | 注册页面 |
| user.html | 用户资料页(查看个人信息) |
| edit_profile.html | 编辑资料页(修改昵称、简介等) |
| note.html | 个人笔记页面(可能是扩展功能) |
| _post.html | 通常是一个“模板片段”,用来循环显示文章(通过 {% include '_post.html' %} 复用) |
6️⃣ static/
作用:存放静态资源文件
如:
-
CSS(样式)
-
JS(脚本)
-
images(图片)
示例:url_for('static', filename='images/bg.jpg')
⚙️ 其他重要文件
🧾 config.py
保存应用配置,比如:
import osclass Config:SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-key'SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:password@localhost/flask_tutorial'SQLALCHEMY_TRACK_MODIFICATIONS = False
📌 Flask 启动时会从这里读取数据库地址、加密密钥等。
🚀 myblog.py
程序入口(相当于 main.py):
from app import app if __name__ == "__main__": app.run(debug=True)
运行:
python myblog.py
就会启动整个 Flask 项目。
🧱 migrations/
由 Flask-Migrate 自动生成,用于数据库版本管理。
运行以下命令后,这里会出现迁移脚本:
flask db init flask db migrate -m "Initial migration" flask db upgrade
🧬 venv/
虚拟环境,包含你项目的所有依赖库。
不要手动改动,安装包时 Flask 会自动放到这里。
✅ 总结图
| 分类 | 代表文件 | 职责 |
|---|---|---|
| 程序核心 | __init__.py, routes.py, models.py | 启动应用、定义路由与数据库模型 |
| 前端展示 | templates/*.html, static/ | 页面结构与样式 |
| 逻辑组件 | forms.py, config.py | 表单逻辑与配置管理 |
| 运行管理 | myblog.py, migrations/, venv/ | 程序入口、数据库迁移、虚拟环境 |
