史上最详细注释,用flask写一个博客系统

文本用flask写个博客系统,源码带有详细注释,通俗易懂,拿去就能用。点 这里 查看演示。博客效果如下,博客首页:

这个博客麻雀虽小,但五脏俱全。有如下功能:

  1. 博客文章浏览
  2. 用户注册
  3. 用户登录/登出
  4. 发文章/修改文章/删除文章

为了简单,没有用MySQL数据,使用了Sqlite数据库。博客来自flask官方教程,用来学习前后端开发,基于模板的后端开发,也能够学习python后端框架flask。因为例子够简单,适合初学者入门,当然前提是,你得有python编程基础。好了,项目的源代码已经传到这里了 flaskr,打开连接看readme.md文档,就知道怎么部署这个博客了(部署就是把博客跑起来!)。源代码添加了详细的注释,方便初学的朋友学习食用。

比如flaksr的主文件:

python 复制代码
import os
from flask import Flask


# 应用工厂函数
def create_app(test_config=None):
    # 设置配置相对于实例文件夹(instance folder),
    # flask从实例文件夹读取配置,而不是flask应用的根目录,
    # __name__是让flask知道自己的位置以设置一些路径,如应用程序的根目录和静态文件目录
    app = Flask(__name__, instance_relative_config=True)

    # 设置app默认配置
    app.config.from_mapping(
        # 保护flask和扩展(extensions)的数据安全
        SECRET_KEY='dev',
        # sqlite文件保存路径
        DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
    )

    # 加载真正的配置
    if test_config is None:
        # config.py文件也存放在实例文件夹中
        app.config.from_pyfile('config.py', silent=True)
    else:
        # 加载测试配置
        app.config.from_mapping(test_config)

    # 创建实例文件夹
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    # 一个简单的路由
    @app.route('/hello')
    def hello():
        return 'Hello, World!'

    # 初始化数据库表
    from . import db
    db.init_app(app)

    # 注册认证(auth)蓝图
    from . import auth
    app.register_blueprint(auth.bp)

    # 注册博客(写博文、看博文等)蓝图
    from . import blog
    app.register_blueprint(blog.bp)

    # 添加一条映射关系:/ -> index,
    # 让url_for('index')返回/,让url_for('blog.index')也返回/(即blog.py的@bp.route('/'))
    app.add_url_rule('/', endpoint='index')

    return app


# 进入flask_tutorial目录,运行app并开启调试模式:
# flask --app flaskr run --debug

# 进入flask_tutorial目录,初始化数据库表:
# flask --app flaskr init-db

还带有pytest测试目录tests,比如tests/test_auth.py文件用来测试认证相关的功能:

python 复制代码
import pytest
from flask import g, session
from flaskr.db import get_db


def test_register(client, app):
    # 测试获取注册页是否符合预期
    assert client.get('/auth/register').status_code == 200

    # 测试提交表单给注册页
    response = client.post(
        # 用字典形式传递数据,测试客户端会转换为表单数据给视图函数
        '/auth/register', data={'username': 'a', 'password': 'a'}
    )

    # 如果注册成功,会跳转到登录页,此时响应头中会有Location字段
    assert response.headers['Location'] == '/auth/login'

    with app.app_context():
        assert get_db().execute(
            'SELECT * FROM user WHERE username="a"',
        ).fetchone() is not None


# 使用pytest参数化测试装饰器,
# 第一个参数指定被装饰的test_register_validate_input测试用例会有三个参数,
# 测试用例的client参数是fixture装饰过的函数,它有参数app,app也是被fixture
# 装饰过的函数,因此pytest会依次:调用app->返回值给client->调用client->
# 返回值给test_register_validate_input。
# 第二个参数元组中有三组数据,pytest会分别传递给测试用例,以便把三种情况都测试一遍,
# 利用参数化测试的好处是不用把测试用例test_register_validate_input重复写三遍
@pytest.mark.parametrize(
    ('username', 'password', 'message'), (
        ('', '', b'Username is required.'),
        ('a', '', b'Password is required.'),
        ('test', 'test', b'already registered'),
    )
)
def test_register_validate_input(client, username, password, message):
    response = client.post(
        '/auth/register',
        data={'username': username, 'password': password}
    )
    # response.data是bytes类型,
    # 测试注册失败的各种情况,看响应体中是否包含对应的错误提示信息
    assert message in response.data


def test_login(client, auth):
    assert client.get('/auth/login').status_code == 200
    response = auth.login()  # 登录 test/test 用户
    assert response.headers['Location'] == '/'
    
    # 在请求之外访问 session 会引发错误,所以使用with上下文
    with client:
        client.get('/')
        assert session['user_id'] == 1
        assert g.user['username'] == 'test'


@pytest.mark.parametrize(
    ('username', 'password', 'message'), (
        ('a', 'test', b'Incorrect username.'),
        ('test', 'a', b'Incorrect password.'),
    )
)
def test_login_validate_input(auth, username, password, message):
    response = auth.login(username, password)
    assert message in response.data


def test_logout(client, auth):
    auth.login()

    with client:
        auth.logout()
        assert 'user_id' not in session

所有的文件,包括源码文件,测试文件,部署说明都在 这里 了。

部署到云服务器,可以用nginx做web服务器,博客代码跑在wsgi服务器上,比如waitress,或者Gunicorn等等。

nginx配置文件可以这样写,创建一个文件flaskr.conf,内容如下:

nginx 复制代码
server {
    listen 80 default_server;
    server_name _;

    # 把所有http请求永久重定向到https
    rewrite ^/(.*) https://$host/$1 permanent;
}

server {
    listen 443 ssl;
    server_name fk.izhaojie.com;    
    index index.html;
    
    # f这是最关键的部分,让nginx把请求转发给flask后端,由wsgi服务处理
    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

完!

相关推荐
这个男人是小帅16 分钟前
【GAT】 代码详解 (1) 运行方法【pytorch】可运行版本
人工智能·pytorch·python·深度学习·分类
码上一元2 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
小白学大数据3 小时前
Python爬虫开发中的分析与方案制定
开发语言·c++·爬虫·python
Shy9604184 小时前
Doc2Vec句子向量
python·语言模型
枫叶_v4 小时前
【SpringBoot】22 Txt、Csv文件的读取和写入
java·spring boot·后端
杜杜的man5 小时前
【go从零单排】Closing Channels通道关闭、Range over Channels
开发语言·后端·golang
java小吕布5 小时前
Java中Properties的使用详解
java·开发语言·后端
2401_857610036 小时前
Spring Boot框架:电商系统的技术优势
java·spring boot·后端
秀儿还能再秀7 小时前
机器学习——简单线性回归、逻辑回归
笔记·python·学习·机器学习
阿_旭8 小时前
如何使用OpenCV和Python进行相机校准
python·opencv·相机校准·畸变校准