5.错误处理

相信到了这里,你应该遇到了许多错误,flask提供的调试模式应该能够很好的帮助你解决这个问题

export FLASK_DEBUG=1
#windows中export换为set

当然flask也能够自定义错误页面,详情可探索官方文档

当然你还可以将日志记录到文件中

#app/__init__.py:登录文件
# ...
from logging.handlers import RotatingFileHandler
import os

# ...

if not app.debug:
    # ...

    if not os.path.exists('logs'):
        os.mkdir('logs')
    file_handler = RotatingFileHandler('logs/myblog.log', maxBytes=10240,
                                       backupCount=10)
    file_handler.setFormatter(logging.Formatter(
        '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
    file_handler.setLevel(logging.INFO)
    app.logger.addHandler(file_handler)

    app.logger.setLevel(logging.INFO)
    app.logger.info('Myblog startup')

6.数据库中的多对多

在这部分中主要实现的是数据库的关系再访,即创作的博客中实现从关注者到被关注者(或者反过来)。

在多对多关系中需要使用一个辅助表,称为关联表。带有两个外键的关联表能够高效回答所有关于关系的问题。

模型表示

#app/models.py:多对多粉丝关系
class User(UserMixin, db.Model):
    # ...
    following: so.WriteOnlyMapped['User'] = so.relationship(
        secondary=followers, primaryjoin=(followers.c.follower_id == id),
        secondaryjoin=(followers.c.followed_id == id),
        back_populates='followers')
    followers: so.WriteOnlyMapped['User'] = so.relationship(
        secondary=followers, primaryjoin=(followers.c.followed_id == id),
        secondaryjoin=(followers.c.follower_id == id),
        back_populates='following')

用户模型变更

#app/models.py:添加和移除关注者
class User(UserMixin, db.Model):
    #...

    def follow(self, user):
        if not self.is_following(user):
            self.following.add(user)

    def unfollow(self, user):
        if self.is_following(user):
            self.following.remove(user)

    def is_following(self, user):
        query = self.following.select().where(User.id == user.id)
        return db.session.scalar(query) is not None

    def followers_count(self):
        query = sa.select(sa.func.count()).select_from(
            self.followers.select().subquery())
        return db.session.scalar(query)

    def following_count(self):
        query = sa.select(sa.func.count()).select_from(
            self.following.select().subquery())
        return db.session.scalar(query)

获取关注用户的帖子

#app/models.py:用用户自己的帖子跟踪帖子查询。在此处扩展了查询逻辑,避免数据膨胀
class User(UserMixin, db.Model):
    #...
    def following_posts(self):
        Author = so.aliased(User)
        Follower = so.aliased(User)
        return (
            sa.select(Post)
            .join(Post.author.of_type(Author))
            .join(Author.followers.of_type(Follower), isouter=True)
            .where(sa.or_(
                Follower.id == self.id,
                Author.id == self.id,
            ))
            .group_by(Post)
            .order_by(Post.timestamp.desc())
        )

在建好表后,需要进行模型的单元测试。python中提供的unittest包,使得这一过程更加轻松。测试通过后将其集成到应用程序中。