当前位置:首页>python>【跟着AI学Python】第30天:简易博客系统(Flask 版)

【跟着AI学Python】第30天:简易博客系统(Flask 版)

  • 2026-10-11 06:51:05
【跟着AI学Python】第30天:简易博客系统(Flask 版)
【Qwen3-Max:】

太棒了!现在我们来完整实现你的简易博客系统(Flask 版) —— MiniBlog!

✅ 无需数据库✅ 纯文件存储(JSON)✅ 包含首页、写文章、详情页三大功能✅ 代码简洁,适合学习和扩展


📁 第一步:创建项目目录结构

在你的工作区创建如下结构:

miniblog/├── app.py├── data/                 # (运行后自动生成)└── templates/    ├── base.html    ├── index.html    ├── post.html    └── write.html

💡 data/ 目录会在首次运行时自动创建,无需手动新建。


📄 第二步:编写核心应用 app.py

# app.pyimport osimport jsonfrom datetime import datetimefrom flask import Flask, render_template, request, redirect, url_forapp = Flask(__name__)DATA_FILE = "data/posts.json"def load_posts():    """从 JSON 文件加载所有文章"""    if not os.path.exists(DATA_FILE):        return []    with open(DATA_FILE, "r", encoding="utf-8") as f:        return json.load(f)def save_posts(posts):    """将文章列表保存到 JSON 文件"""    os.makedirs(os.path.dirname(DATA_FILE), exist_ok=True)    with open(DATA_FILE, "w", encoding="utf-8") as f:        json.dump(posts, f, ensure_ascii=False, indent=2)def get_next_id(posts):    """获取下一个文章 ID"""    if not posts:        return 1    return max(post["id"] for post in posts) + 1@app.route("/")def index():    """首页:显示所有文章(倒序)"""    posts = load_posts()    # 按时间倒序(最新在前)    posts.sort(key=lambda x: x["created_at"], reverse=True)    return render_template("index.html", posts=posts)@app.route("/write", methods=["GET", "POST"])def write():    """写文章页面"""    if request.method == "POST":        title = request.form.get("title", "").strip()        content = request.form.get("content", "").strip()        if not title or not content:            return "标题和内容不能为空!", 400        posts = load_posts()        new_post = {            "id": get_next_id(posts),            "title": title,            "content": content,            "created_at": datetime.now().strftime("%Y-%m-%d %H:%M")        }        posts.append(new_post)        save_posts(posts)        return redirect(url_for("index"))    return render_template("write.html")@app.route("/post/<int:post_id>")def post(post_id):    """文章详情页"""    posts = load_posts()    post = next((p for p in posts if p["id"] == post_id), None)    if not post:        return "文章未找到", 404    return render_template("post.html", post=post)if __name__ == "__main__":    app.run(debug=True)

🖼️ 第三步:创建模板文件

1. templates/base.html(基础布局)

<!-- templates/base.html --><!DOCTYPE html><htmllang="zh-CN"><head>    <metacharset="UTF-8">    <metaname="viewport"content="width=device-width, initial-scale=1.0">    <title>{% block title %}MiniBlog{% endblock %}</title>    <style>        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }        header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #eee; padding-bottom: 10px; margin-bottom: 20px; }        .post { margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px dashed #ccc; }        .post-meta { color: #666; font-size: 0.9em; }        textarea, input[type=text] { width: 100%; padding: 8px; margin: 5px 0; box-sizing: border-box; }        button { background: #4CAF50; color: white; padding: 10px 20px; border: none; cursor: pointer; }        button:hover { background: #45a049; }        a { color: #2196F3; text-decoration: none; }        a:hover { text-decoration: underline; }    </style></head><body>    <header>        <h1><ahref="{{ url_for('index') }}">MiniBlog</a></h1>        <ahref="{{ url_for('write') }}">✍️ 写文章</a>    </header>    {% block content %}{% endblock %}</body></html>

2. templates/index.html(首页 - 文章列表)

<!-- templates/index.html -->{% extends "base.html" %}{% block content %}{% if posts %}    {% for post in posts %}    <divclass="post">        <h2><ahref="{{ url_for('post', post_id=post.id) }}">{{ post.title }}</a></h2>        <divclass="post-meta">{{ post.created_at }}</div>        <p>{{ post.content[:100] }}{% if post.content|length > 100 %}...{% endif %}</p>    </div>    {% endfor %}{% else %}    <p>📭 还没有文章,<ahref="{{ url_for('write') }}">去写一篇吧</a>!</p>{% endif %}{% endblock %}

3. templates/write.html(写文章表单)

<!-- templates/write.html -->{% extends "base.html" %}{% block title %}写文章 - MiniBlog{% endblock %}{% block content %}<h2>✍️ 写新文章</h2><formmethod="POST">    <labelfor="title">标题:</label>    <inputtype="text"id="title"name="title"required>    <labelfor="content">内容:</label>    <textareaid="content"name="content"rows="10"required></textarea>    <buttontype="submit">发布文章</button>    <ahref="{{ url_for('index') }}"style="margin-left: 10px;">取消</a></form>{% endblock %}

4. templates/post.html(文章详情)

<!-- templates/post.html -->{% extends "base.html" %}{% block title %}{{ post.title }} - MiniBlog{% endblock %}{% block content %}<ahref="{{ url_for('index') }}">← 返回首页</a><h2>{{ post.title }}</h2><divclass="post-meta">{{ post.created_at }}</div><divstyle="margin-top: 20px; line-height: 1.6;">    {{ post.content.replace('\n', '<br>')|safe }}</div>{% endblock %}

🔒 安全说明:{{ ... |safe }} 表示信任内容(因为我们自己写的文章)。若未来支持用户评论,需改用自动转义!


▶️ 第四步:运行项目

  1. 确保已安装 Flask:

    pip install Flask
  2. 启动应用:

    python app.py
  3. 访问:

    • 首页:http://127.0.0.1:5000
    • 写文章:点击右上角 “✍️ 写文章”
    • 查看文章:点击首页任意标题

🧪 运行效果图及测试流程

  1. 打开首页 → 显示“还没有文章”
  2. 点击“写文章” → 填写标题和内容 → 点击“发布”
  3. 自动跳回首页 → 显示新文章(带摘要)
  4. 点击文章标题 → 进入详情页,显示完整内容(保留换行)

✅ 首次运行后,data/posts.json 会自动生成并保存数据!


📝 项目亮点总结

特性
实现方式
无数据库
用 posts.json 存储
自动 ID 生成max(id) + 1
时间戳datetime.now().strftime()
安全 HTML 输出
Jinja2 默认转义 + `
响应式样式
内联 CSS(简单美观)

🚀 后续可扩展方向(学有余力可尝试)

  1. 添加 Markdown 支持
    # 安装: pip install markdownimport markdownhtml_content = markdown.markdown(post['content'])
  2. 增加文章编辑/删除功能
  3. 分页显示文章
  4. 部署到云服务器(如 PythonAnywhere)

🎉 恭喜!你的 MiniBlog 已成功运行!

现在,去写你的第一篇博客吧!比如:《我的 Python 学习之旅》✨😊

最新文章

随机文章