Appearance
简易博客系统是前面六章知识的综合应用:项目设计 → 数据模型 → 模块开发(入口/用户/文章/管理),实现文章发布、分类、搜索、阅读量统计、留言、博客设置、友情链接等完整功能。学完本章即具备开发简单 Flask 应用的能力。
项目设计流程
- 项目需求:文章发布、分类、搜索、阅读量统计、留言、博客信息展示、友情链接
- 模块设计:拆成 4 个模块——入口模块(首页/公共功能)、用户模块(注册登录/认证)、文章模块(列表/搜索/留言)、管理模块(后台,建立于其他模块之上)
- 数据模型设计:先画模型设计图(属性 + 关系),再转代码,用 Flask-Migrate 生成数据库
- 功能实现:模板放
templates/,Python 代码放各模块目录
数据模型总览(关系图)
| 模型 | 表名 | 关键字段 | 关系 |
|---|---|---|---|
| UserModel | user | id, username(unique), password, is_admin | 1–1 UserInfo;1–N Article、Comment |
| UserInfoModel | user_info | user_id(主键/外键), nickname, phone, email, introduce | 与 User 一对一 |
| CategoryModel | category | id, name(unique) | 1–N Article |
| ArticleModel | article | id, author_id(外键), category_id(外键), title, content, create_time, update_time, view_count | N–1 User、Category;1–N Comment |
| CommentModel | comment | id, author_id(外键), article_id(外键), content, create_time | N–1 User、Article |
| FriendLinkModel | friend_link | id, name, url | 无 |
| SettingModel | setting | id, key(unique), value(JSON 字符串) | 无 |
关键设计点:
- 时间用
db.INTEGER存时间戳(time.time()),查询排序用id.desc()或时间字段 - 外键加
index=True提升查询性能 view_count默认 0,用于阅读量统计- SettingModel 用 key-value + JSON 存"全站唯一"的设置项(不用单独建表)
入口模块(portal)
- FriendLinkModel / SettingModel:友情链接与设置模型(见上表)
- 设定存取:
load_setting(key)/save_setting(key, value)用json.loads/dumps读写 JSON 字符串;把包内所有 callable 通过app.add_template_global(f)注册为模板全局对象 - 公共模板:
common/base.html继承 bootstrap 基准页,用{% include %}引入导航栏/右侧栏/页尾;导航栏拆分子菜单nav_menu/category.html(文章分类下拉)、nav_menu/user.html(用户登录态菜单) - 首页:
load_setting('site_setting')取home_per_page,按id.desc()取最新 N 篇文章 - CKEditor 上传:配置
CKEDITOR_SERVE_LOCAL=True、CKEDITOR_FILE_UPLOADER='portal.upload'、UPLOADED_PATH;上传视图校验扩展名(jpg/gif/png/jpeg),send_from_directory提供静态文件
用户模块(user)
- 注册:RegisterForm(用户名/密码/手机号正则
\d{11}/邮箱/自我介绍)→ 建 UserModel + UserInfoModel →dh.session.add/commit→ flash 后跳登录 - 登录:LoginForm(含"记住登录状态"remember)→ 查库 →
login_user(item, form.remember.data)→ 重定向next参数或当前页 - 注销:
@login_required+logout_user() - 查看/编辑:
/user/<int:id>查用户详情;/user/edit用get_current_user()修改,密码留空不改
文章模块(article)
- 宏指令
article/macros.html:generate_article(article, is_full)生成单篇文章 HTML(is_full=False 时标题带链接、内容striptags | truncate截断);generate_articles(articles)循环生成列表,空列表提示"作者偷懒啦" - 最新文章列表 / 搜索:
paginate(None, per_page)分页;搜索用 SQLAlchemyor_(title.contains(keyword), content.contains(keyword));两者共用article/list.html(标题作为变量注入) - 文章分类:
/category/<name>按分类名查 CategoryModel,再按category_id过滤分页,复用列表模板 - 查看文章 + 阅读量 + 留言(一页三功能):
- 阅读量:
article_view_count(item)用 session 存已读文章 id 列表session['article_view_ids'],同一用户不重复计数 - 留言表单:
CKEditorField富文本;POST 路由@login_required,create_time=time.time() - 留言列表:宏
generate_comments(comments)+ 分页
- 阅读量:
管理模块(admin,后台)
- 蓝图组织:
admin = Blueprint('admin', __name__),子模块admin_article / admin_portal / admin_user / admin_friend_link分别url_prefix='/admin/article'等 @admin_required:包装@login_required+is_admin检查(见第六章),普通用户访问返回 403- 后台基准页
admin/base.html:与前台类似但去页尾、全页面显示、加左侧菜单栏 - 用户管理:列表(分页 + 编辑/删除链接)→ 编辑(UserEditForm,含 is_admin 布尔字段、密码留空不改)→ 删除(按 id 删 + flash)
- 文章管理:ArticleAddForm(title/category/content CKEditorField)→ add 时
item.category = get_category(form.category.data);编辑用ArticleEditForm(ArticleAddForm)仅换提交按钮文字 - 友情链接管理:FriendLinkAddForm / FriendLinkEditForm,增删改查四件套
- 博客设置(两种设置,同一模板):
- 系统设置 SystemSettingForm:网站名称、页尾、各页面每页条数(admin_per_page/home_per_page/category_per_page/list_all_per_page/search_per_page/comment_per_page)
- 信息设置 InfoSettingForm:博客标题、描述、"关于"信息
- 三个工具函数:
_setting_inject_form(数据注入表单)、_form_export_setting(表单导出字典,剔除 submit/csrf_token)、视图内save_setting('site_setting', setting)
开发模式总结("三步走")
每个管理功能都是同一种套路:
定义表单类 → 视图函数(GET 展示 / POST 校验→入库→flash→重定向)→ 模板页(继承后台基准页 + wtf.quick_form)后台所有视图统一 @admin_required,模板统一 {% extends 'admin/base.html' %},列表页统一"表格 + render_pagination"。
项目结构(综合版)
项目根/
├── manage.py / config.py / run.py
└── app/
├── __init__.py(create_app 工厂 + 蓝图注册 + 模板全局注册)
├── database.py(BaseModel + DatabaseHelper)
├── portal/(入口:首页/设置/友情链接/CKEditor 上传)
├── user/(用户:注册/登录/注销/信息)
├── article/(文章:列表/搜索/分类/查看/留言)
└── admin/(后台:user/article/portal/friend_link 子模块)
templates/(含 common/ 公共模板、各模块模板)
static/(blog.css、admin/dashboard.css)实践建议
- 开发顺序:先设计数据模型 → 生成数据库 → 按"入口 → 用户 → 文章 → 管理"逐模块开发(管理模块依赖其他模块)
- 模板层多用**继承(base)+ 包含(nav/right)+ 宏(article 列表)**三层复用,公共内容只写一遍
- 设置类数据(全站唯一、低频)用 key-value + JSON 存储,不必为它建完整表结构
- 阅读量防刷:session 记录已读文章 id,天然防同一浏览器重复计数
- 每个管理功能都是"表单 + 视图 + 模板"三步走,学会一个就能批量复制
一句话总结
这是前六章的综合落地:先画数据模型,再按"入口 → 用户 → 文章 → 管理"逐模块开发;每个后台功能都是同一套路——定义表单类 → 视图函数校验后入库 → 模板用 wtf.quick_form 渲染。