0
点赞
收藏
分享

微信扫一扫

Flask实现个人博客系统(附源码)

静悠 2022-05-03 阅读 116
  • 写博客:写博客采用的Markdown编辑器完成的。可以发布自己的博客

  • 我的博客:查看自己发布的博客并对其管理

  • 我的评论:查看自己的所有评论并对其管理

  • 修改密码

  • 查看博客列表:查看所有已发布的博客

  • 博客详情页:查看博客内容及评论信息,可以对当前博客进行评论

  • 关于

[](()项目目录


在这里插入图片描述

[](()数据库设计


数据库一共设计了三张表:用户表、博客表、评论表。

表之间的映射关系如下:

在这里插入图片描述

用户表和博客表一对多关系;用户和评论表一对多关系;博客表和评论表一对多关系。

其表的模型类代码如下:

class User(db.Model):

设置表名

tablename = ‘tb_user’;

id,主键并自动递增

id = db.Column(db.Integer, primary_key=True, autoincrement=True)

username = db.Column(db.String(64), unique=True)

password = db.Column(db.String(256), nullable=True)

name = db.Column(db.String(64))

设置只可写入,对密码进行加密

def password_hash(self, password):

self.password = generate_password_hash(password);

class Blog(db.Model):

tablename = ‘blog’

id = db.Column(db.Integer, primary_key=True, autoincrement=True)

title = db.Column(db.String(128))

text = db.Column(db.TEXT)

create_time = db.Column(db.String(64))

#关联用户id

user_id = db.Column(db.Integer, db.ForeignKey(‘tb_user.id’))

user = db.relationship(‘User’, backref=‘user’)

class Comment(db.Model):

tablename = ‘comment’

id = db.Column(db.Integer, primary_key=True, autoincrement=True)

text = db.Column(db.String(256)) # 评论内容

create_time = db.Column(db.String(64))

关联博客id

blog_id = db.Column(db.Integer, db.ForeignKey(“blog.id”))

关联用户id

user_id = db.Column(db.Integer, db.ForeignKey(“tb_user.id”))

blog = db.relationship(“Blog”, backref=“blog”)

user = db.relationship(“User”, backref=“use”)

[](()功能实现


[](()页面基本模板实现

页面使用的是Jinja2模板,Jinja2支持页面继承,所以导航栏重复性的页面代码,我们都可以写在一个文件中。这里我们先创建一个base.html文件,编写页面大致的框架。其他模块直接继承使用即可。

{% block title %}

{# 其他页面可以重写标题 #}

{% endblock %}

{% block css %}

{% endblock %}

    • 在线博客平台
    • {% if username %}

    • 修改密码
    • {% endif %}

    • 博客
    • 关于
    • {% if username %}

    • {{ name }}

      我的博客
      我的评论
      注销
    • 写博客
    • {% else %}

    • 注册
    • {% endif %}

      {% block content %}

      {# 其他页面内容 #}

      {% endblock %}

      这里页面使用了Layui定义了一个导航栏,展示了对应的功能模块。其中{% if username %},username为后台存放在session中的一个键值对,用于判断用户是否登录了,有些功能登录后才显示。

      base.html模板文件完成后,我们在定义一个index.html来做项目的首页,直接继承base.html。这样首页index.html就节省了很多代码。如下:

      {% extends ‘base.html’ %}

      {% block title %}

      在线博客平台

      {% endblock %}

      {% block content %}

      在线博客平台

      {% endblock %}

      首页效果如下:

      [](()登录与注册功能

      登录

      先定义一个登录的视图函数,可以接收GET、POST请求,GET请求为跳转到登录页面,POST请求为处理登录提交的请求,验证是否登录成功,登录成功后把当前登录对象的用户名存入session会话中。

      登录请求

      @index.route(‘/login’, methods=[‘POST’, ‘GET’])

      def login():

      if request.method == ‘GET’:

      return render_template(‘login.html’)

      if request.method == ‘POST’:

      username = request.form.get(‘username’)

      password = request.form.get(‘password’)

      user = User.query.filter(User.username == username).first();

      check_password_hash比较两个密码是否相同

      if (user is not None) and (check_password_hash(user.password, password)):

      session[‘username’] = user.username

      session.permanent = True

      return redirect(url_for(‘index.hello’))

      else:

      flash(“账号或密码错误”)

      return render_template(‘login.html’);

      登录页面是用Layui写的一组form表单,也是基础的base.html,代码如下:

      {% extends ‘base.html’ %}

      {% block title %}

      在线博客平台.登录

      {% endblock %}

      {% block css %}

      {% endblock %}

      {% block content %}

      登录

      {% for item in get_flashed_messages() %}

      {{ item }}

      {% endfor %}

      立即提交

      重置

      {% endblock %}

      {% block login_class %}

      layui-this

      {% endblock %}

      效果如下(账号和密码错误后,会有相应的提示信息):在这里插入图片描述

      注册和登录差不多,页面都是使用的同一个css样式文件,所以这里就贴代码出来了,需要的可以自行下载完整项目代码:GitHub地址。

      [](()修改密码

      修改密码模块,因为数据库存放明文密码很不安全,所以这里使用了Werkzeug对密码进行了加密存储。对于WerkZeug密码加密想进一步了解的,可以访问[Flask 使用Werkzeug实现密码加密。

      ](()

      因为数据库中存储的是加密后的密码,所以这里判断原密码是否正确需要使用check_password_hash函数进行判断。

      定义一个修改密码的视图函数。

      修改密码

      @index.route(“/updatePwd”, methods=[‘POST’, ‘GET’])

      @login_limit

      def update():

      if request.method == “GET”:

      return render_template(“updatePwd.html”)

      if request.method == ‘POST’:

      lodPwd = request.form.get(“lodPwd”)

      newPwd1 = request.form.get(“newPwd1”)

      newPwd2 = request.form.get(“newPwd2”)

      username = session.get(“username”);

      user = User.query.filter(User.username == username).first();

      if check_password_hash(user.password, lodPwd):

      if newPwd1 != newPwd2:

      flash(“两次新密码不一致!”)

      return render_template(“updatePwd.html”)

      else:

      user.password_hash(newPwd2)

      db.session.commit();

      flash(“修改成功!”)

      return render_template(“updatePwd.html”)

      else:

      flash(“原密码错误!”)

      return render_template(“updatePwd.html”)

      页面样式文件和登录注册引入的样式文件一致(原密码不正确或两次新密码不同,会给出相应的提示信息),代码如下:

      {% extends ‘base.html’ %}

      {% block title %}

      在线博客平台.修改密码

      {% endblock %}

      {% block css %}

      {% endblock %}

      {% block content %}

      修改密码

      {% for item in get_flashed_messages() %}

      {{ item }}

      {% endfor %}

      立即提交

      {% endblock %}

      {% block updatepwd_class %}

      layui-this

      {% endblock %}

      效果如下:

      在这里插入图片描述

      [](()写博客

      写博客,博客表中会保存标题、博客内容、当前时间等字段。如下是写博客的视图函数。

      写博客页面

      @blog.route(‘/writeBlog’, methods=[‘POST’, ‘GET’])

      @login_limit

      def writeblog():

      if request.method == ‘GET’:

      return render_template(‘writeBlog.html’)

      if request.method == ‘POST’:

      title = request.form.get(“title”)

      text = request.form.get(“text”)

      username = session.get(‘username’)

      获取当前系统时间

      create_time = time.strftime(“%Y-%m-%d %H:%M:%S”)

      user = User.query.filter(User.username == username).first()

      blog = Blog(title=title, text=text, create_time=create_time, user_id=user.id)

      db.session.add(blog)

      db.session.commit();

      blog = Blog.query.filter(Blog.create_time == create_time).first();

      return render_template(‘blogSuccess.html’, title=title, id=blog.id)

      保存博客时会获取到当前系统时间,当做博客的发布时间。博客保存成功后,会返回保存成功页面,下面会有讲解。

      写博客对应的html文件,代码如下。

      {% extends ‘base.html’ %}

      {% block title %}

      在线博客平台.写博客

      {% endblock %}

      {% block css %}

      {% endblock %}

      {% block content %}

      保存

      {% endblock %}

      {% block write_class %}

      layui-this

      {% endblock %}

      写博客这里采用的是Markdown编辑器,对于Markdown编辑器之前写过一篇Markdown的使用方法,只不过后端用的是Java语言,感兴趣的小伙伴可以看看,[Markdown的基本使用。](()Flask与之不同的是,后端接收Markdown上传图片时的语句不同,Flask接收Markdown上传图片的语句:

      file = request.files.get(‘editormd-image-file’);

      其他的基本相同,毕竟Markdown是属于前端的知识,后端只要求根据规定个格式返回数据即可。

      因为Markdown支持图片上传,那就必须的有文件上传的方法了。如下定义一个文件上传的视图函数(这里需要注意的是Markdown上传图片是使用的POST方法)。

      上传图片

      @blog.route(‘/imgUpload’, methods=[‘POST’])

      @login_limit

      def imgUpload():

      try:

      file = request.files.get(‘editormd-image-file’);

      fname = secure_filename(file.filename);

      ext = fname.rsplit(‘.’)[-1];

      生成一个uuid作为文件名

      fileName = str(uuid.uuid4()) + “.” + ext;

      filePath = os.path.join(“static/uploadImg/”, fileName);

      file.save(filePath)

      return {

      ‘success’: 1,

      ‘message’: ‘上传成功!’,

      ‘url’: “/” + filePath

      }

      except Exception:

      return {

      ‘success’: 0,

      ‘message’: ‘上传失败’

      }

      如果对上述的文件上传代码比较陌生,可以访问[Flask 文件上传与下载]((),对Flask文件上传与下载进一步了解。

      效果如下:

      在这里插入图片描述

      保存成功后,会返回保存成功页面,可以在写一篇,或者查看当前发布的文章。

      在这里插入图片描述

      [](()查看博客列表

      查看博客列表就是遍历所有已发布的博客。先定义一个视图函数,查询所有已发布的博客,传递到前端进行遍历显示。视图函数代码如下:

      展示全部博客

      @blog.route(“/blogAll”)

      def blogAll():

      order_by按照时间倒序

      blogList = Blog.query.order_by(Blog.create_time.desc()).all();

      return render_template(‘blogAll.html’, blogList=blogList)

      因为最新发布的博客在数据库的最后一条,所以这里根据发布时间倒序查询。

      页面代码如下:

      {% extends ‘base.html’ %}

      {% block title %}

      在线博客平台.博客

      {% endblock %}

      {% block css %}

      {% endblock %}

      {% block content %}

        {% for blog in blogList %}

      • {{ blog.title }}

        发布人:{{ blog.user.name }}     发布时间:{{ blog.create_time }}

        {% endfor %}

        {% endblock %}

        {% block blog_class %}

        layui-this

        {% endblock %}

        效果如下:

        在这里插入图片描述

        [](()博客详情页面

        在博客列表中点击博客的标题可以进入博客的详情页面,详情页面展示了博客的详细内容以及评论内容。

        因为数据库中保存博客内容的是Markdown格式的,所以在这里需要解析成HTML格式,解析代码如下。

        editormd.markdownToHTML(“test”, {

        htmlDecode: “style,script,iframe”,

        emoji: true,

        taskList: true,

        tex: true, // 默认不解析

        flowChart: true, // 默认不解析

        sequenceDiagram: true // 默认不解析

        });

        [](()评论

        在博客详情页面可以进行评论,评论使用的是Layui的编辑器,比较简约也可以达到想要的效果。效果如图。

        在这里插入图片描述

        看上去是不是还可以,和页面也很搭。评论需要先登录才可以评论,如果没有登录则会提示登录。

        在这里插入图片描述

        如果登录评论后,会发送保存评论请求,携带当前博客的id和评论内容进行保存。

        保存评论的视图函数

        评论

        @blog.route(“/comment”, methods=[‘POST’])

        @login_limit

        def comment():

        text = request.values.get(‘text’)

        blogId = request.values.get(‘blogId’)

        username = session.get(‘username’)

        获取当前系统时间

        create_time = time.strftime(“%Y-%m-%d %H:%M:%S”)

        user = User.query.filter(User.username == username).first()

        comment = Comment(text=text, create_time=create_time, blog_id=blogId, user_id=user.id)

        db.session.add(comment)

        db.session.commit();

        return {

        ‘success’: True,

        ‘message’: ‘评论成功!’,

        }

        上述的博客内容解析与评论都在一个页面中,完整代码如下。

        {% extends ‘base.html’ %}

        {% block title %}

        在线博客平台.博客

        {% endblock %}

        {% block css %}

      举报

      相关推荐

      0 条评论