Python 实战:简易 Flask 博客项目

舞姬之光
发布: 2025-09-21 16:50:01
原创
626人浏览过
用Python和Flask搭建简易博客,可直观理解Web开发核心。1. 创建虚拟环境并安装Flask、Flask-SQLAlchemy等库;2. 编写app.py定义应用实例、数据库模型(Post)、表单(PostForm)及路由(首页、文章详情、创建文章);3. 使用Jinja2模板引擎构建base.html、index.html、post_detail.html和create_post.html,实现页面布局与内容渲染;4. 添加static/css/style.css美化界面;5. 集成markdown库解析Markdown内容,并通过highlight.js实现代码高亮;6. 运行app.py生成blog.db数据库,访问本地服务即可使用。该方案以轻量级框架提供高度灵活性,适合学习Web全流程开发。

python 实战:简易 flask 博客项目

用 Python 和 Flask 搭建一个简易博客,其实是理解现代 Web 应用开发核心概念最直接、最有趣的方式之一。它能让你亲手串联起前端展示、后端逻辑、数据库存储以及用户交互,从零开始构建一个能跑起来的网站,这种成就感是实打实的。


构建一个简易的 Flask 博客,我们通常会从几个核心组件入手:一个 Flask 应用实例作为骨架,SQLAlchemy 来处理数据库交互,Jinja2 模板引擎负责页面渲染,以及一些静态文件来美化界面。

首先,你需要设置一个隔离的开发环境。创建一个虚拟环境,然后安装必要的库:

pip install Flask Flask-SQLAlchemy Flask-WTF Markdown
登录后复制

接下来,我们逐步构建应用:

立即学习Python免费学习笔记(深入)”;

1. 应用骨架 (

app.py
登录后复制
blog.py
登录后复制
)
这是你的 Flask 应用入口。

from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Length
import markdown # 用于解析Markdown内容
import os

# 配置应用
app = Flask(__name__)
app.config['SECRET_KEY'] = '一个非常安全的秘密密钥,生产环境请用复杂随机字符串' # 用于CSRF保护
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db' # 使用SQLite数据库
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# 数据库模型
class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    # 可以添加发布日期、作者等字段

    def __repr__(self):
        return f'<Post {self.title}>'

# 表单定义
class PostForm(FlaskForm):
    title = StringField('标题', validators=[DataRequired(), Length(min=1, max=100)])
    content = TextAreaField('内容', validators=[DataRequired()])
    submit = SubmitField('发布')

# 路由定义
@app.route('/')
def index():
    posts = Post.query.order_by(Post.id.desc()).all()
    return render_template('index.html', posts=posts)

@app.route('/post/<int:post_id>')
def post_detail(post_id):
    post = Post.query.get_or_404(post_id)
    # 将Markdown内容转换为HTML
    post_html_content = markdown.markdown(post.content, extensions=['fenced_code'])
    return render_template('post_detail.html', post=post, post_html_content=post_html_content)

@app.route('/create', methods=['GET', 'POST'])
def create_post():
    form = PostForm()
    if form.validate_on_submit():
        new_post = Post(title=form.title.data, content=form.content.data)
        db.session.add(new_post)
        db.session.commit()
        flash('文章发布成功!', 'success')
        return redirect(url_for('index'))
    return render_template('create_post.html', form=form)

# 运行应用
if __name__ == '__main__':
    with app.app_context():
        db.create_all() # 在应用上下文中创建数据库表
    app.run(debug=True)
登录后复制

2. 模板文件 (

templates/
登录后复制
) 你需要创建
base.html
登录后复制
作为基础布局,
index.html
登录后复制
展示文章列表,
post_detail.html
登录后复制
展示单篇文章,以及
create_post.html
登录后复制
用于创建文章。

  • templates/base.html
    登录后复制

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>{% block title %}我的简易博客{% endblock %}</title>
      <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css"> {# 代码高亮样式 #}
    </head>
    <body>
      <nav>
          <a href="{{ url_for('index') }}">首页</a>
          <a href="{{ url_for('create_post') }}">发布文章</a>
      </nav>
      <div class="container">
          {% with messages = get_flashed_messages(with_categories=true) %}
              {% if messages %}
                  <ul class="flashes">
                  {% for category, message in messages %}
                      <li class="{{ category }}">{{ message }}</li>
                  {% endfor %}
                  </ul>
              {% endif %}
          {% endwith %}
          {% block content %}{% endblock %}
      </div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> {# 代码高亮脚本 #}
      <script>hljs.highlightAll();</script> {# 初始化代码高亮 #}
    </body>
    </html>
    登录后复制
  • templates/index.html
    登录后复制

    {% extends "base.html" %}
    {% block title %}文章列表 - 我的简易博客{% endblock %}
    {% block content %}
      <h1>所有文章</h1>
      {% for post in posts %}
          <article class="post-summary">
              <h2><a href="{{ url_for('post_detail', post_id=post.id) }}">{{ post.title }}</a></h2>
              {# 这里可以展示文章摘要,或者不显示,直接点击进入详情 #}
          </article>
      {% else %}
          <p>还没有任何文章。</p>
      {% endfor %}
    {% endblock %}
    登录后复制
  • templates/post_detail.html
    登录后复制

    {% extends "base.html" %}
    {% block title %}{{ post.title }} - 我的简易博客{% endblock %}
    {% block content %}
      <article class="post-detail">
          <h1>{{ post.title }}</h1>
          <div class="post-content">
              {{ post_html_content|safe }} {# 渲染Markdown转换为HTML的内容 #}
          </div>
      </article>
    {% endblock %}
    登录后复制
  • templates/create_post.html
    登录后复制

    {% extends "base.html" %}
    {% block title %}发布新文章 - 我的简易博客{% endblock %}
    {% block content %}
      <h1>发布新文章</h1>
      <form method="POST">
          {{ form.csrf_token }}
          <div>
              {{ form.title.label }}<br>
              {{ form.title(size=60) }}
              {% if form.title.errors %}
                  <ul class="errors">
                  {% for error in form.title.errors %}
                      <li>{{ error }}</li>
                  {% endfor %}
                  </ul>
              {% endif %}
          </div>
          <div>
              {{ form.content.label }}<br>
              {{ form.content(rows=15, cols=80) }}
              {% if form.content.errors %}
                  <ul class="errors">
                  {% for error in form.content.errors %}
                      <li>{{ error }}</li>
                  {% endfor %}
                  </ul>
              {% endif %}
          </div>
          <div>
              {{ form.submit() }}
          </div>
      </form>
    {% endblock %}
    登录后复制

3. 静态文件 (

static/css/style.css
登录后复制
) 为了让页面看起来不那么简陋,可以加一点基础样式。

body {
    font-family: sans-serif;
    margin: 0;
    padding: 0;
    background-color: #f4f4f4;
    color: #333;
}
.container {
    max-width: 800px;
    margin: 20px auto;
    padding: 20px;
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
nav {
    background-color: #333;
    padding: 10px 0;
    text-align: center;
}
nav a {
    color: #fff;
    text-decoration: none;
    padding: 10px 15px;
    margin: 0 5px;
}
nav a:hover {
    background-color: #555;
    border-radius: 4px;
}
h1, h2 {
    color: #333;
}
.post-summary {
    border-bottom: 1px solid #eee;
    padding-bottom: 15px;
    margin-bottom: 15px;
}
.post-summary:last-child {
    border-bottom: none;
}
.post-summary h2 a {
    text-decoration: none;
    color: #007bff;
}
.post-summary h2 a:hover {
    text-decoration: underline;
}
.flashes {
    list-style: none;
    padding: 0;
    margin: 10px 0;
}
.flashes li {
    padding: 10px;
    margin-bottom: 10px;
    border-radius: 5px;
}
.flashes .success {
    background-color: #d4edda;
    color: #155724;
    border: 1px solid #c3e6cb;
}
/* Markdown content styling */
.post-content img {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 1em auto;
}
.post-content blockquote {
    border-left: 4px solid #ccc;
    padding-left: 10px;
    color: #666;
    margin: 1em 0;
}
.post-content pre {
    background-color: #f8f8f8;
    padding: 10px;
    border-radius: 5px;
    overflow-x: auto;
}
.post-content code {
    font-family: monospace;
    background-color: #eee;
    padding: 2px 4px;
    border-radius: 3px;
}
.post-content pre code {
    background-color: transparent;
    padding: 0;
}
登录后复制

将这些文件放置在正确的目录结构中:

your_blog_project/
├── app.py
├── blog.db (首次运行后生成)
├── templates/
│   ├── base.html
│   ├── index.html
│   ├── post_detail.html
│   └── create_post.html
└── static/
    └── css/
        └── style.css
登录后复制

运行

python app.py
登录后复制
,然后在浏览器中访问
http://127.0.0.1:5000
登录后复制
,你就能看到一个最基础的博客了。从这里开始,你可以根据自己的需求添加用户认证、评论系统、文章编辑/删除功能等。

为什么选择 Flask 而不是 Django 来构建博客?

选择 Flask 来构建一个简易博客,对我来说,更多的是一种哲学上的偏好。Django 确实是“电池已包含”的框架,它提供了 ORM、管理后台、表单处理、认证系统等一切开箱即用的功能。如果你想快速搭建一个功能完备、结构复杂的应用,Django 绝对是效率的保证。它就像一个装修好的精装房,拎包入住。

博思AIPPT
博思AIPPT

博思AIPPT来了,海量PPT模板任选,零基础也能快速用AI制作PPT。

博思AIPPT 40
查看详情 博思AIPPT

但 Flask 就不一样了,它是一个微框架,只提供最核心的 WSGI 工具包和路由功能。这意味着你需要手动选择和集成数据库、表单、认证等各种组件。这种“自己动手”的感觉,对于初学者或者想深入理解 Web 工作原理的人来说,简直是福音。你可以清楚地看到每个组件是如何协同工作的,而不是被框架的“魔法”所掩盖。对于一个“简易博客”而言,Django 可能显得有些杀鸡用牛刀,它的许多内置功能我们可能根本用不上。Flask 的轻量级和灵活性,让我们可以从最基础的 HTTP 请求响应开始,一步步搭建出我们想要的功能,这种掌控感是无与伦比的。

如何为 Flask 博客选择合适的数据库?SQLite 够用吗?

为 Flask 博客选择数据库,其实是个挺有意思的问题,因为它直接关系到项目的复杂度和未来的扩展性。对于一个“简易博客”项目,我几乎可以毫不犹豫地说:SQLite 绝对够用,而且是初期最好的选择。

SQLite 是一个文件型的数据库,这意味着它不需要独立的数据库服务器进程,所有数据都存储在一个

.db
登录后复制
文件中。它的优点显而易见:零配置、易于部署、轻量级。在开发阶段,你不需要安装和配置 MySQL 或 PostgreSQL 这样的独立数据库服务,直接在你的项目中创建一个
.db
登录后复制
文件,然后 Flask-SQLAlchemy 就能轻松连接并操作它。这大大降低了入门门槛和开发环境的复杂性。

当然,如果你的博客未来流量巨大,需要处理高并发读写,或者数据量非常庞大,那么 SQLite 的性能瓶颈就会显现出来。那时,你可能就需要考虑切换到 PostgreSQL 或 MySQL 这样的关系型数据库,它们提供了更强大的事务处理、并发控制和数据完整性保障。但好在,Flask-SQLAlchemy 这样的 ORM 库,在很大程度上抽象了底层数据库的差异。这意味着,如果你一开始用 SQLite 搭建,未来需要升级时,修改数据库连接字符串和少量配置,通常就能迁移到其他数据库,而无需重写大部分模型代码。所以,从简易博客开始,用 SQLite 是一个非常明智且实用的选择。

博客文章如何实现 Markdown 支持和代码高亮?

在博客中实现 Markdown 支持和代码高亮,是提升写作体验和内容展示质量的关键一步。毕竟,谁也不想在写文章时被繁琐的 HTML 标签困扰,或者让代码块看起来像一堆乱码。

实现 Markdown 支持,核心思路是利用一个 Python 库将 Markdown 文本转换成 HTML。

markdown
登录后复制
库就是其中一个非常流行且易于使用的选择。你只需要
pip install markdown
登录后复制
,然后在你的 Flask 应用中,当从数据库取出文章内容准备渲染到页面时,用
markdown.markdown()
登录后复制
函数处理一下即可。

例如,在

post_detail
登录后复制
路由中,我们从数据库获取到文章内容
post.content
登录后复制
,然后:

import markdown
# ...
@app.route('/post/<int:post_id>')
def post_detail(post_id):
    post = Post.query.get_or_404(post_id)
    # 将Markdown内容转换为HTML
    # extensions=['fenced_code'] 允许我们使用 ```python 这样的语法来定义代码块
    post_html_content = markdown.markdown(post.content, extensions=['fenced_code'])
    return render_template('post_detail.html', post=post, post_html_content=post_html_content)
登录后复制

在模板中,记得用

|safe
登录后复制
过滤器来告诉 Jinja2,这段 HTML 是安全的,不需要转义:

<div class="post-content">
    {{ post_html_content|safe }}
</div>
登录后复制

至于代码高亮,这通常是前端 JavaScript 库的职责。

highlight.js
登录后复制
Prism.js
登录后复制
是两个非常优秀的选项。它们的工作原理相似:你需要在页面中引入它们的 CSS 样式和 JavaScript 脚本,然后它们会自动扫描页面中的
<pre><code>...</code></pre>
登录后复制
标签,并根据代码语言(通过
class="python"
登录后复制
这样的类名指定)应用高亮样式。

highlight.js
登录后复制
为例:

  1. 引入 CSS 和 JS:
    base.html
    登录后复制
    <head>
    登录后复制
    部分引入
    highlight.js
    登录后复制
    的样式文件,并在
    <body>
    登录后复制
    结束标签前引入其脚本文件。
    <head>
        {# ... 其他样式 ... #}
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
    </head>
    <body>
        {# ... 页面内容 ... #}
        <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
        <script>hljs.highlightAll();</script> {# 初始化代码高亮 #}
    </body>
    登录后复制
  2. 编写 Markdown 时指定语言: 当你在文章内容中插入代码块时,使用 Markdown 的 Fenced Code Blocks 语法,并指定语言:
    ```python
    def hello_flask():
        return "Hello, Flask!"
    登录后复制
    这样,当 Markdown 被转换成 HTML 后,`highlight.js` 就能识别出 `<code>` 标签内的代码,并应用漂亮的高亮效果了。这个过程把内容的编写和展示解耦,让你的博客既美观又易用。
    登录后复制

以上就是Python 实战:简易 Flask 博客项目的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号