Python中使用Flask搭建博客网站过程解析(第3节)


在上一节教程中,我们成功使用Flask搭建了一个简易的博客网站。本节教程我们将详细讲解博客网站的工作原理。

1、项目结构解析

打开上一节教程中介绍的Flask博客网站项目目录,可以看到项目的基本目录如下所示:

blog
├── app.py
├── templates
      ├── index.html
      ├── about.html
      ├── add.html
      ├── login.html
      ├── signin.html
      └── update.html
└── static
        ├── home-bg.jpg
        └── about-bg.jpg

app.py(文件):Python的运行程序,用来定义应用程序的路由和应用逻辑代码等。

templates(文件夹):项目所用到的html文件存放目录。Flask框架在调用render_template()模板函数时,会默认去寻找项目文件夹下的templates文件夹里的html静态模板文件。

static(文件夹):项目所用到的除html文件以外的静态文件存放目录,用来存放程序所用到的css、fonts、img、js文件。static文件夹里面的图片文件可以在html模板代码中使用“<img src="../static/home-bg.jpg" class="" alt=""> ”标签加载图片。

html(文件):html文件是一种纯文本格式的文件,是用于创建网页的标准标记语言文件。我们经常使用到的网页文件后缀名包括“.html”和“.htm”, 一个“.html”或者“.htm”文件就是一个网页,html文件用编辑器打开显示的是文本,可以用文本的方式编辑它,如果用浏览器打开,浏览器会按照标签描述的内容将文件渲染成网页。我们用编辑器打开html文件可以看到里面大部分都是固定格式的标签, <标签名称> </标签名称>, 比如: <html></html>、<div></div>、<h1></h1> 等,标签大多数都是成对出现的。html文件是构建网站的基础。通过html,开发者可以创建动态的、交互的网页,使用户可以通过浏览器访问并浏览网页内容。此外,html还可以与CSS和JavaScript等技术结合使用,实现更复杂的功能和更丰富的视觉效果。在第23章“HTML基础学习”中我们将详细讲解HTML的基础知识。

2、app.py文件代码解析

(1)创建数据库

在app.py中,Flask框架创建Web应用比较简单,但是要想实现用户登录功能,就必须使用数据库来存储用户数据,从而更好地管理Web应用。

在Flask应用中,我们可以使用SQLAlchemy这个库来操作关系型数据库。它支持多种数据库,包括MySQL、PostgreSQL、SQLite等等。

在上一节教程中,我们已经通过终端命令“pip install Flask-SQLAlchemy”安装了SQLAlchemy库,接下来,在app.py中,我们需要导入SQLAlchemy模块,并创建一个数据库连接,代码如下:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blogs.db'
db = SQLAlchemy(app)

上述代码中,我们使用Flask应用实例的config属性来配置数据库的连接信息,这里我们配置了一个SQLite数据库。然后,我们使用SQLAlchemy模块的SQLAlchemy类创建一个数据库连接实例db。SQLite是一个小型的轻量级数据库,它不需要额外的数据库服务器,同时它也是内嵌在Python中的。与其他数据库相比,SQLite要小得多,因为它不需要维护大量的服务,而且不会造成压力。这使得SQLite在嵌入式设备、单机应用程序和移动应用程序等方面被广泛运用。

(2)定义数据模型

在app.py中,我们需要为博客文章定义一个数据模型类。这个类需要继承自db.Model类,并定义一些属性来映射到数据库表中的列。我们将其命名为FLASKBLOG,代码如下:

class FLASKBLOG(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(50))
    author = db.Column(db.String(20))
    post_date = db.Column(db.DateTime)
    content = db.Column(db.Text)

上述代码中,我们定义了一个FLASKBLOG类,它继承自db.Model类。类中定义了5个属性:

id:整型,用来标识每一条记录的唯一性。我们使用db.Column类来定义它,并通过primary_key=True参数来指定它为主键。

title:字符串类型,用来存储博客的标题。我们同样使用db.Column类来定义它。

author:字符串类型,用来存储作者的名字。

post_date:时间字段,用来存储发博客的时间。

author:长文本数据类型,用来存储博客的内容。

接下来,我们需要使用db.create_all()方法来创建数据库表,代码如下:

db.create_all()

在app.py中,我们还需要为用户注册过程定义一个数据模型类。这个类同样需要继承自db.Model类,同时还继承flask_login模块中的UserMixin类。UserMixin类是一个用于用户身份验证和授权的辅助类。我们将其命名为User,代码如下:

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), nullable=False, unique=True)
    password = db.Column(db.String(80), nullable=False)

上述代码中,我们定义了一个User类,它继承自db.Model类和UserMixin类。类中定义了3个属性:

id:整型,用来标识每一条记录的唯一性。我们使用db.Column类来定义它,并通过primary_key=True参数来指定它为主键。

username:字符串类型,用来存储用户名,我们同样使用db.Column类来定义它。这里将nullable设置为false时,表示该字段不允许为空,并通过unique=True参数来指定它为唯一性约束。注意,设置为unique=True后,该表会为该字段中建立一个唯一索引,该字段数据在该表中就只能是唯一的了,所以在注册用户时,不可创建相同的用户名,否则会报错。

password:字符串类型,用来存储用户密码,同样通过nullable=False参数来表示该字段不允许为空。

(3)表单处理

在app.py中,我们想要为用户实现登录功能,就必须为用户处理提交的表单数据。使用Flask框架,可以轻松地处理表单数据,并对其进行验证和处理。

首先,在login.html模板中创建一个表单,可以使用<form>标签和各种表单元素(如输入框、复选框、下拉 列表等)。例如:

<form class="modal-content animate" action="/login" method="POST">
    <div class="container">
        <label for="uname"><b>用户名</b></label>
        <input type="text" placeholder="请输入用户名" name="username" id="username" required>
        <label for="psw"><b>密码</b></label>
        <input type="password" placeholder="请输入密码" name="password" id="password" required>
        <button type="submit">登录</button>
        <label><input type="checkbox" checked="checked" name="remember">记住账号</label>
    </div>
    <div class="container" style="background-color:#f1f1f1">
        <button type="button" onclick="window.location.href = '/'"; class="cancelbtn">取消登录</button>
        <span class="psw">如果未注册,请先<a href="/signin">注册</a></span>
    </div>
</form>

在这个登录表单中,使用了<form>标签来创建一个表单,并设置了method属性为“POST”,action属性为“/login”,表示表单数据将通过POST请求提交到“/login”路由。

接下来,在app.py中定义一个处理登录表单的路由和视图函数。可以使用request对象来获取表单数据。例如:

from flask_login import login_user

@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        user = User.query.filter_by(username=username).first()
        if user and user.password == password:
            login_user(user)
            return redirect(url_for('hello_world'))
        elif not user:
            flash('用户名不存在,请先注册')
        else:
            flash('密码错误')
    return render_template('login.html')

上面的例子中,我们定义了一个“/login”路由,用于处理login.html模板中登录表单提交的数据。在“login()”视图函数中,使用request.form['username']方法来获取login.html表单中提交的用户名输入值,使用request.form['password']方法来获取login.html表单中提交的密码输入值。

在这里,我们从登录页面获取了用户输入的用户名和密码字段的值,并分别赋值给“username”和“password”两个变量,通过SQLAlchemy库的query.filter_by(字段名=值).first()方法,在数据库中执行有条件的查询,“.first()”方法则用于限制查询结果只返回一个对象,‌即查询结果中的第一个对象,最后通过if语句简单地验证。

如果用户名和密码验证通过,就可以通过flask_login模块中login_user()函数将用户登录状态设置为已登录,‌这样用户就可以有权限发博客、更改博客、删除博客等操作。‌login_user()是flask_login模块中的一个重要函数,‌用于将用户登录到应用中。