Skip to content

简易博客系统是前面六章知识的综合应用:项目设计 → 数据模型 → 模块开发(入口/用户/文章/管理),实现文章发布、分类、搜索、阅读量统计、留言、博客设置、友情链接等完整功能。学完本章即具备开发简单 Flask 应用的能力。

项目设计流程

  1. 项目需求:文章发布、分类、搜索、阅读量统计、留言、博客信息展示、友情链接
  2. 模块设计:拆成 4 个模块——入口模块(首页/公共功能)、用户模块(注册登录/认证)、文章模块(列表/搜索/留言)、管理模块(后台,建立于其他模块之上
  3. 数据模型设计:先画模型设计图(属性 + 关系),再转代码,用 Flask-Migrate 生成数据库
  4. 功能实现:模板放 templates/,Python 代码放各模块目录

数据模型总览(关系图)

模型表名关键字段关系
UserModeluserid, username(unique), password, is_admin1–1 UserInfo;1–N Article、Comment
UserInfoModeluser_infouser_id(主键/外键), nickname, phone, email, introduce与 User 一对一
CategoryModelcategoryid, name(unique)1–N Article
ArticleModelarticleid, author_id(外键), category_id(外键), title, content, create_time, update_time, view_countN–1 User、Category;1–N Comment
CommentModelcommentid, author_id(外键), article_id(外键), content, create_timeN–1 User、Article
FriendLinkModelfriend_linkid, name, url
SettingModelsettingid, 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=TrueCKEDITOR_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/editget_current_user() 修改,密码留空不改

文章模块(article)

  • 宏指令 article/macros.htmlgenerate_article(article, is_full) 生成单篇文章 HTML(is_full=False 时标题带链接、内容 striptags | truncate 截断);generate_articles(articles) 循环生成列表,空列表提示"作者偷懒啦"
  • 最新文章列表 / 搜索paginate(None, per_page) 分页;搜索用 SQLAlchemy or_(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_requiredcreate_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)

实践建议

  1. 开发顺序:先设计数据模型 → 生成数据库 → 按"入口 → 用户 → 文章 → 管理"逐模块开发(管理模块依赖其他模块)
  2. 模板层多用**继承(base)+ 包含(nav/right)+ 宏(article 列表)**三层复用,公共内容只写一遍
  3. 设置类数据(全站唯一、低频)用 key-value + JSON 存储,不必为它建完整表结构
  4. 阅读量防刷:session 记录已读文章 id,天然防同一浏览器重复计数
  5. 每个管理功能都是"表单 + 视图 + 模板"三步走,学会一个就能批量复制

一句话总结

这是前六章的综合落地:先画数据模型,再按"入口 → 用户 → 文章 → 管理"逐模块开发;每个后台功能都是同一套路——定义表单类 → 视图函数校验后入库 → 模板用 wtf.quick_form 渲染。

相关概念