Python轻量级Web框架Flask(13)—— Flask个人博客项目

0、前言:

  • ★这部分内容是基于之前Flask学习内容的一个实战项目梳理内容,没有可以直接抄下来跑的代码,是学习了之前Flask基础知识之后,再来看这部分内容,就会对Flask项目开发流程有更清楚的认知,对一些开发细节可以进一步的学习。
  • 项目功能,通过Flask制作个人博客。
  • 项目架构:项目分为两部分,第一部分是展示给别人的前端页面,第二部分是展示给自己的后台数据管理页面。
  • 该项目是前后端不分离项目
  • 在搭建一个项目之前一定要先把数据库设计好,把数据库中的表设计好,表和表之间的关系弄清楚

1、项目设计流程:

  • 数据库设计 > 架构设计 > 代码实现

2、架构设计:

  • 1、由于项目中视图函数可能会有多个,因此最好是通过设计views的python包来管理视图函数,因此在views包中有两个视图函数文件一个是views管理展示给别人的视图函数,views_admin管理展示给自己的后台数据管理的视图函数。
  • 2、同理由于该项目需要也设置了models的python包将数据分为前端展示数据(models)和后台数据(models_admin)两部分。做完这两部分修改后,注意在初始化中修改导包,修改app绑定的蓝图,有了两个视图函数文件,就会有两个蓝图,一个蓝图叫blog管理前端页面,一个蓝图叫admin管理博客后台管理系统。

3、数据库设计:

  • 1、models中数据表设计:【分类表(1):文章表(N)、相册表】
  • 2、models_admin中数据表设计:【用户信息表】
    在这里插入图片描述

4、项目框架展示

在这里插入图片描述

  • 1、注意项目中用到的图片有两种添加方式,图片在数据表中是通过url的方式存储的,添加图片第一种方式是数据服务器,第二种方式是使用静态文件,一般正规公司项目开发都是使用静态文件的方式,通过数据服务器存放图片url。
  • 2、因为views和models都分为了两个包,分别存放展示页面与后台管理页面相关内容,所以这两部分的页面和这两部分的数据库是分开的,因此这两部分视图函数也是分开的,功能上互不干预。

5、项目主要文件代码展示

  • 1、app
# Flask个人博客项目
from App import creat_app
app = creat_app()
if __name__ == '__main__':
    app.run(debug=True)
  • 2、models
# models.py : 模型,数据库

'''
    模型      ===      数据库
    类        ——>     表结构
    类属性     ——>    表字段
    一个对象   ——>    表的一行数据
'''
from ..exts import db # 导入db对象就能通过python实现ORM技术,避免了写SQL语句。

# 分类数据表
class CategoryModel(db.Model):
    # 表名
    __tablename__ = 'tb_category'   # 数据迁移就是让模型变成表,ORM就是让类变成模型
    # 定义表字段
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(30), unique=True)
    describe = db.Column(db.Text(), default='describe')
    # 关联外键(可以在分类表中获取对应的所有文章)
    articles = db.relationship('ArticleModel', backref='category', lazy='dynamic')


# 文章数据表
class ArticleModel(db.Model):
    # 表名
    __tablename__ = 'tb_article'   # 数据迁移就是让模型变成表,ORM就是让类变成模型
    # 定义表字段
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(30), unique=True)
    keyword = db.Column(db.String(255), default='keyword')
    content = db.Column(db.Text(), default='content')
    img = db.Column(db.Text(), default='img')
    # 外键
    category_id = db.Column(db.Integer, db.ForeignKey(CategoryModel.id))

# 相册
class PhotoModel(db.Model):
    # 表名
    __tablename__ = 'tb_photo'
    # 定义表字段
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    url = db.Column(db.Text())
    name = db.Column(db.String(30), unique=True)
    describe = db.Column(db.Text(), default='describe')
  • 3、models_admin
from ..exts import db # 导入db对象就能通过python实现ORM技术,避免了写SQL语句。

# 模型Model:类
# 必须继承 db.Model User才能从普通的类变成模型
class AdminUserModel(db.Model):
    # 表名
    __tablename__ = 'tb_adminuser'   # 数据迁移就是让模型变成表,ORM就是让类变成模型
    # 定义表字段
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(30), unique=True)
    passwd = db.Column(db.String(30))
    # 通过orm技术得到的db,就是用于替代数据库,后面用到数据库相关操作,可以检索。
  • 4、views
# 在views.py中放路由和视图函数

from flask import Blueprint, render_template, request
from ..models.models import * #后面是用views来控制数据库的,所以要在views中导入models文件

# 蓝图(蓝图可以有多个,方便对路径进行区分)
blog = Blueprint('blog', __name__)

# 博客首页
@blog.route('/')
@blog.route('/index/')
def index():
    # 修改首页中“我的相册”当中的6张图,调用photos数据库中前6张图片
    # 修改首页中“文章分类”
    # 修改首页中“iKun推荐”
    # 修改首页中右侧的文章
    photos = PhotoModel.query.limit(6)
    categories = CategoryModel.query.all()
    articles = ArticleModel.query.all()
    commend_arc = articles[:4]
    return render_template('home/index.html',
                           photos=photos,
                           categories=categories,
                           articles=commend_arc,
                           arts = articles)

# 我的相册
@blog.route('/photos/')
def blog_photos():
    photos = PhotoModel.query.all()
    return render_template('home/photos.html', photos = photos)

# 我的日记
@blog.route('/article/')
def blog_aritcle():
    articles = ArticleModel.query.all()
    categories = CategoryModel.query.all()
    return render_template('home/article.html', articles = articles, categories = categories)

# 关于我
@blog.route('/about/')
def blog_about():
    photos1 = PhotoModel.query.all()
    categories = CategoryModel.query.all()
    photos = photos1[:6]
    return render_template('home/about.html', photos = photos, categories = categories)
  • 4、views_admin
# 在views.py中放路由和视图函数

from flask import Blueprint, render_template, request, redirect, jsonify
from ..models.models_admin import * #后面是用views来控制数据库的,所以要在views中导入models文件
from ..models.models import * # 首页面需要查询models当中的表
import time
# 蓝图(蓝图可以有多个,方便对路径进行区分)
admin = Blueprint('admin', __name__)

# ---------------------- 后台管理 ----------------------
# 装饰器:做登录验证,就不用每次都写一遍登陆验证了
from functools import wraps # 为了在多个函数使用装饰器时,能够让函数名正确传递
def login_required(fn):
    @wraps(fn)
    def inner(*args, **kwargs):
        # 判断用户是否登录
        # 获取cookie,得到登录的用户
        user_id = request.cookies.get('user_id', None)
        if user_id:
            # 登陆过,进入后台管理系统
            user = AdminUserModel.query.get(user_id)
            request.user = user
            return fn(*args, **kwargs) # 登陆过就去调用对应的视图函数
        else:
            # 没有登陆过,跳转到登录页面
            return redirect('/admin/login/')
    return inner

# 后台管理——首页面
@admin.route('/admin/')
@admin.route('/admin/index/')
@login_required
def index():
    # user_id = request.cookies.get('user_id', None) # 默认值给空,如果没有的话,默认为空
    # if user_id:
    #     # 登陆过或登录成功,有cookie的情况
    #     user = AdminUserModel.query.get(user_id)
    #     categorys = CategoryModel.query.filter()
    #     articles = ArticleModel.query.filter()
    #     photos = PhotoModel.query.filter()
    #     return render_template('admin/index.html',
    #                            username = user.name,
    #                            categorys=categorys,
    #                            articles=articles,
    #                            photos=photos)
    # else:
    #     return redirect('/admin/login/')

    user = request.user
    categorys = CategoryModel.query.filter()
    articles = ArticleModel.query.filter()
    photos = PhotoModel.query.filter()
    return render_template('admin/index.html',
                           username=user.name,
                           categorys=categorys,
                           articles=articles,
                           photos=photos)


# 后台管理——登录
@admin.route('/admin/login/',methods=['GET', 'POST'])
def admin_login():
    if request.method == 'GET': # 网页向服务器请求数据
        return render_template('admin/login.html')
    elif request.method == 'POST': # 网页向服务器提交数据
        username = request.form.get('username') # 用户名
        userpwd = request.form.get('userpwd') # 密码
        # 登陆验证
        user = AdminUserModel.query.filter_by(name = username, passwd = userpwd).first()
        if user:
            # 登陆成功
            response = redirect('/admin/index/')
            '''
            1、回顾下cookie的工作流程:前端发送请求-后端返回前端一个cookie-前端保存cookie-前端在cookie有效期
            登录可以免密登录。
            2、注意下面设置response的cookie中参数时,'user_id'是cookie的名称, str(user.id)是cookie的值,
            cookie值要求必须是每个用户独一无二的。
            '''
            response.set_cookie('user_id', str(user.id), max_age=7*12*3600) # cookie设置7天有效
            return response
        else:
            return 'login failed'

# 后台管理——退出登录
@admin.route('/admin/logout/')
def admin_logout():
    response = redirect('/admin/login/')
    response.delete_cookie('user_id')
    return response

# ---------------------- 后台管理——分类管理 ----------------------
@admin.route('/admin/category/')
@login_required
def admin_category():
    user = request.user
    categories = CategoryModel.query.all()
    return render_template('/admin/category.html',
                           username = user.name,
                           categories = categories)

# 分类页面添加分类功能实现
@admin.route('/admin/addcategory/', methods=['GET','POST'])
@login_required
def add_category():
    if request.method == 'POST':
        name = request.form.get('name')
        describe = request.form.get('describe')
        # 添加分类(在数据表中创建一条数据就是创建一个对象)
        category = CategoryModel()
        category.name = name
        category.describe = describe
        try:
            db.session.add(category)
            db.session.commit()
        except Exception as e:
            print('e',e)
            db.session.rollback()
        return redirect('/admin/category/') # 不论成功还是失败,重新跳转,相当于刷新了页面
    return '请求方式错误'

# 分类页面删除分类功能实现
@admin.route('/admin/delcategory/', methods=['GET','POST'])
@login_required
def del_category():
    if request.method == 'POST':
        # 先查询
        id = request.form.get('id')
        # print(id)
        category = CategoryModel.query.get(id)
        # 再删除
        try:
            db.session.delete(category)
            db.session.commit()
        except Exception as e:
            print('e:',e)
        return  jsonify({'code':200,'msg':'删除成功!'})
    else:
        return jsonify({'code':400,'msg':'请求方式错误!'})

# 分类页面修改分类功能实现
@admin.route('/admin/updatecategory/<id>/', methods=['GET','POST'])
@login_required
def update_category(id):
    user = request.user
    if request.method == 'GET':
        category = CategoryModel.query.get(id)
        return render_template('admin/category_update.html',
                               username = user.name,
                               category=category)
    elif request.method == 'POST':
        name = request.form.get('name')
        describe = request.form.get('describe')
        # 修改
        category = CategoryModel.query.get(id)
        category.name = name
        category.describe = describe
        # 提交
        try:
            db.session.commit()
        except Exception as e:
            print('e:',e)
            db.session.rollback()
        return redirect('/admin/category/')
    else:
        return "请求方式错误!"
# ---------------------- 后台管理——文章管理 ----------------------
# 文章管理
@admin.route('/admin/article/')
@login_required
def admin_article():
    user = request.user
    articles = ArticleModel.query.all()
    return render_template('/admin/article.html',
                           username = user.name,
                           articles = articles)
# 删除文章
@admin.route('/admin/delarticle/', methods=['GET','POST'])
@login_required
def del_article():
    if request.method == 'POST':
        id = request.form.get('id')
        article = ArticleModel.query.get(id)
        try:
            db.session.delete(article)
            db.session.commit()
        except Exception as e:
            print('e:',e)
            db.session.rollback()
            return jsonify({'code': 500, 'msg': '删除失败'})
        return jsonify({'code':200, 'msg':'删除文章成功' })
    return jsonify({'code':400, 'msg':'请求方式错误!' })
# 添加文章
@admin.route('/admin/addarticle/', methods=['GET','POST'])
@login_required
def add_article():
    if request.method == 'GET':
        categories = CategoryModel.query.all()
        articles = ArticleModel.query.all()
        return render_template('/admin/article_add.html',
                               username = request.user.name,
                               articles = articles,
                               categories = categories)
    elif request.method == 'POST':
        # 添加文章
        name = request.form.get('name')
        keywords = request.form.get('keywords')
        content = request.form.get('content')
        category = request.form.get('category')
        img = request.files.get('img')
        # 图片存储路径
        img_name = f'{time.time()}-{img.filename}'
        img_url = f'/static/home/uploads/{img_name}'
        # 添加文章
        try:
            article = ArticleModel()
            article.name = name
            article.keyword = keywords
            article.content = content
            article.img = img_url
            article.category_id = category

            db.session.add(article)
            db.session.commit()
        except Exception as e:
            print('e:',e)
            db.session.rollback()
            db.session.flush()
        else:
            # 如果添加数据库成功,就要把图片存入本地
            img_data = img.read()
            with open(f'App/{img_url}','wb') as fp:
                fp.write(img_data)
                fp.flush()

        return redirect('/admin/article')

# 修改文章
@admin.route('/admin/updatearticle/<id>/', methods=['GET','POST'])
@login_required
def upddate_article(id):
    article = ArticleModel.query.get(id)
    if request.method == 'GET':
        categories = CategoryModel.query.all()
        return render_template('/admin/article_update.html/',
                               username=request.user.name,
                               categories=categories,
                               article=article)
    elif request.method == 'POST':
        # 修改文章
        name = request.form.get('name')
        keywords = request.form.get('keywords')
        content = request.form.get('content')
        category = request.form.get('category')
        img = request.files.get('img')
        # 图片存储路径
        img_name = f'{time.time()}-{img.filename}'
        img_url = f'/static/home/uploads/{img_name}'
        # 添加文章
        try:
            article.name = name
            article.keyword = keywords
            article.content = content
            article.img = img_url
            article.category_id = category

            db.session.commit()
        except Exception as e:
            print('e:', e)
            db.session.rollback()
            db.session.flush()
        else:
            # 如果添加数据库成功,就要把图片存入本地
            img_data = img.read()
            with open(f'App/{img_url}', 'wb') as fp:
                fp.write(img_data)
                fp.flush()

        return redirect('/admin/article')
  • 5、exts
from flask_sqlalchemy import SQLAlchemy # orm技术
from flask_migrate import Migrate # 数据迁移技术

db = SQLAlchemy()
migrate = Migrate()

def init_exts(app):
    db.init_app(app=app)
    migrate.init_app(app=app, db=db)
  • App的init
# __init__.py : 初始化文件,创建Flask应用
from flask import Flask
from .views.views import blog
from .views.views_admin import admin
from .exts import init_exts


def creat_app():
    app = Flask(__name__)
    # 注册蓝图
    app.register_blueprint(blueprint=blog)
    app.register_blueprint(blueprint=admin)

    # 配置数据库(配置不同数据库软件,就要用不同配置,配置的目的,就是在用到数据库的时候让项目知道找什么数据库,去哪找数据库)
    # db_uri = 'sqlite:///sqlite3.db'
    db_uri = 'mysql+pymysql://root:123456@localhost:3306/blogdb' # mysql的配置
    app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 禁止对象追踪修改(为了不浪费服务器资源进行的设置)
    # 初始化插件
    init_exts(app=app)
    return app

6、用户管理页面与展示页面设计:

  • 1、可以先把展示页面设计出来,放上写死的数据,然后通过项目的视图函数调用调试,让前端页面先跑通,然后再给后端添加测试数据,通过结合模板语言修改前端代码,实现后台数据与前端页面的交互展示。【注意:前后端交互本质,就是将后端数据库当中数据表的数据拿到后,准确给到前端对应位置即可,因为有时候传递数据较多,通过模板语言就能更有逻辑的显示后端传递过来的数据,放到前端对应位置。】
    在这里插入图片描述
  • 2、其中分为admin(用户管理页面)、home(展示页面),展示页面中index是首页,photos是相册页面,article是我的日记页面,about是关于我页面;用户管理页面中index是后台管理的首页面,login是后台管理的登录页面,category是分类管理页面,category_update是在category页面中点击修改分类后跳转的页面,article是文章,article_add是添加文章,article_update是修改文章数据表。

7、展示页面数据交互方式

  • 1、展示页面数据交互流程图
    在这里插入图片描述
  • 2、前端页面的修改其实很简单,就是在views(视图函数)中通过数据表查询到需要传递的数据,然后在前端中通过“模板语言”把传递过来的数据渲染到前端页面即可,如下所示就是一个前端页面渲染的例子:
    在这里插入图片描述

8、用户管理页面实现:增、删、改、查

8.1、关键问题概述

  • 1、后端页面设计的登录页面中,关于cookie的设置和返回问题,可以参考“Flask会话技术”,设置了cookie,就可以保持登录一段时间,下次登录时间如果在保持登录时间内,就能用cookie登录进去,只有通过退出登录,才能删除cookie。
  • 2、后端数据往前端传递的过程:先查询到相关数据,然后通过render_template通过逗号隔开挨个传递数据。
  • 3、前端往后端传递数据的过程:先通过flask当中内置的request对象访问客户端发送给服务器的请求信息,然后将对应的信息通过flask当中的表操作,传递给数据表。
  • 4、前端向后端传递数据的方式是:POST;后端向前端传递参数,前端获取数据的方式是:GET,写视图函数的时候,通过这两个参数区分。
  • 5、图片通过网页上传到后端,后端可以给图片存储到项目路径下的文件夹当中。 但是要注意同一文件夹中不能有名字相同的图片,所以可以导入时间,将每个文件上传的时间戳加文件名,就不会有重名了。 一般是先将图片的url存放到数据表中,然后通过文件操作,手动将文件存放到对应url中。

8.2、关键问题详述

  • 1、如何实现后台登录验证:
    如下面的代码中,首先通过装饰器模板写好内部函数inner,在inner中进行判断,如果从cookies中得到了user_id,就证明了之前有登陆过,就可以获取user_id,否则就返回None给到user_id。如果有登录过,就从inner函数中调用外部函数fn,fn就是对应跳转页面的视图函数,就能够跳转到相应的页面中。下面的首页面加了登录验证的装饰器,就可以做登录判断了,当然也可以每个视图函数都写一次登录判断。
# 装饰器:做登录验证,就不用每次都写一遍登陆验证了
from functools import wraps # 为了在多个函数使用装饰器时,能够让函数名正确传递
def login_required(fn):
    @wraps(fn)
    def inner(*args, **kwargs):
        # 判断用户是否登录
        # 获取cookie,得到登录的用户
        user_id = request.cookies.get('user_id', None)
        if user_id:
            # 登陆过,进入后台管理系统
            user = AdminUserModel.query.get(user_id)
            request.user = user
            return fn(*args, **kwargs) # 登陆过就去调用对应的视图函数
        else:
            # 没有登陆过,跳转到登录页面
            return redirect('/admin/login/')
    return inner
# 登录首页的视图函数
@admin.route('/admin/')
@admin.route('/admin/index/')
@login_required
def index():
    user = request.user
    categorys = CategoryModel.query.filter()
    articles = ArticleModel.query.filter()
    photos = PhotoModel.query.filter()
    return render_template('admin/index.html',
                           username=user.name,
                           categorys=categorys,
                           articles=articles,
                           photos=photos)
  • 2、如何实现对数据表的添加操作:
    以该项目中的 类型数据表 为例,如下图,可以看到该数据库中主要的字段有三个:id、name、describe,由于id是自增长的,所以只需要有name和describe就可以添加一条数据给到数据表。
    在这里插入图片描述
    因此,后台管理页面中,给 类型数据表 添加新类型,就需要设计一个新的页面来收集name和describe这两个字段,如下图所以就是给 类型数据表 添加新类型的页面。
    在这里插入图片描述
    当然,这个功能也一定是通过Flask当中的视图函数实现的。如下所示的视图函数add_category就实现了该功能,首先,添加路由装饰器和登陆验证装饰器,因为是添加数据,需要把页面表单中的数据提交到后台的视图函数中,所以视图函数首先会判断request的方式是不是POST,如果是,就说明表单正在往视图函数提交数据,这个时候,视图函数就可以通过request(全局对象,在flask处理请求时自动创建)获取到表单当中提交过来的数据,然后创建数据表对象,给字段赋值,然后尝试添加到数据表当中即可。添加完成后,重定向到分类页面,重定向就可以重新加载一次,就能够看到我们添加数据的操作是否成功。
# 以下代码写在views_admin.py当中

# 分类页面添加分类功能实现
@admin.route('/admin/addcategory/', methods=['GET','POST'])
@login_required
def add_category():
    if request.method == 'POST':
        name = request.form.get('name')
        describe = request.form.get('describe')
        # 添加分类(在数据表中创建一条数据就是创建一个对象)
        category = CategoryModel()
        category.name = name
        category.describe = describe
        try:
            db.session.add(category)
            db.session.commit()
        except Exception as e:
            print('e',e)
            db.session.rollback()
        return redirect('/admin/category/') # 不论成功还是失败,重新跳转,相当于刷新了页面
    return '请求方式错误'

这个过程也是需要前端代码配合才行,如下就是前端表单的html代码,可以看到,表单中两处input都是通过name命名的,这样,就能在视图函数中通过request获取对应的表单内容。

<form action="/admin/addcategory/" method="post" autocomplete="off">
   <div class="form-group">
        <label for="category-name">分类名称</label>
        <input type="text" id="category-name" name="name" class="form-control"
               placeholder="在此处输入分类名称" required autocomplete="off">
    </div>
    <div class="form-group">
        <label for="category-describe">分类描述</label>
        <textarea class="form-control" id="category-describe" name="describe" rows="4"
                  autocomplete="off"></textarea>
    </div>
    <button class="btn btn-primary" type="submit" name="submit">添加新分类</button>
</form>
  • 3、如何实现对数据表的删除操作:
    同样以该项目中的 类型数据表 为例,如下图所示,就是分类管理中展示的所有 类型数据表 的值,通过html当中的a标签实现删除操作
    在这里插入图片描述
    首先通过html当中的代码,可以看出,删除操作相对复杂,需要通过js向视图函数提交要删除数据的id,然后再接收来自视图函数的消息,判断是否删除成功,如果删除成功,就在js当中刷新页面。
{% for category in categories %}
   <tr>
       <td>{{ category.id }}</td>
       <td>{{ category.name }}</td>
       <td>
           <a href="/admin/updatecategory/{{ category.id }}/">修改</a>
           <a href="#" cid="{{ category.id }}">删除</a>
       </td>
   </tr>
{% endfor %}

<script>
    //是否确认删除
    $(function () {
        $("#main table tbody tr td a").click(function () {
            var that = $(this);
            var id = that.attr("cid"); //对应id
            if (event.srcElement.outerText === "删除") {
                if (window.confirm("此操作不可逆,是否确认?")) {
                    $.post('/admin/delcategory/', {'id': id}, function (data){
                        console.log(data.msg)
                        if (data.code == 200){
                            location.reload()
                        }
                    })

                }
            }
        })
    });
</script>

对于视图函数而言,删除操作就是只需要知道你想删除的数据在数据表中对应的id,然后通过表操作直接删除该数据即可。

# 以下代码写在views_admin.py当中

# 分类页面删除分类功能实现
@admin.route('/admin/delcategory/', methods=['GET','POST'])
@login_required
def del_category():
    if request.method == 'POST':
        # 先查询
        id = request.form.get('id')
        # print(id)
        category = CategoryModel.query.get(id)
        # 再删除
        try:
            db.session.delete(category)
            db.session.commit()
        except Exception as e:
            print('e:',e)
        return  jsonify({'code':200,'msg':'删除成功!'})
    else:
        return jsonify({'code':400,'msg':'请求方式错误!'})
  • 4、如何实现对数据表的修改操作:
    同样以该项目中的 类型数据表 为例,参考 对数据表的删除操作 讲解中的前端页面截图和html代码即可,可以知道,通过模板语言加载过程中,就已经可以通过 category.id 拿到分类表中要修改的数据的id了,通过a连接跳转到路由 /admin/updatecategory/{{ category.id }}/ 对应的新页面,这个过程中带着参数即可,然后这个参数就会被传递到该路由对应的视图函数当中,视图函数如下,注意路由写的时候也要带着参数,由于a标签打开路由页面的请求是GET请求,所以在判断请求方式是GET时,就能获取到传递过来的参数id,然后通过id,查找到对应的数据表当中的数据对象。
# 以下代码写在views_admin.py当中

# 分类页面修改分类功能实现
@admin.route('/admin/updatecategory/<id>/', methods=['GET','POST'])
@login_required
def update_category(id):
    user = request.user
    if request.method == 'GET':
        category = CategoryModel.query.get(id)
        return render_template('admin/category_update.html',
                               username = user.name,
                               category=category)
    elif request.method == 'POST':
        name = request.form.get('name')
        describe = request.form.get('describe')
        # 修改
        category = CategoryModel.query.get(id)
        category.name = name
        category.describe = describe
        # 提交
        try:
            db.session.commit()
        except Exception as e:
            print('e:',e)
            db.session.rollback()
        return redirect('/admin/category/')
    else:
        return "请求方式错误!"

然后,将查到的数据同模板(admin/category_update.html)一同打开,如下图所示就是修改页面中,对应修改数据填充后的展示结果。
在这里插入图片描述
admin/category_update.html(修改页面)中html就会有一个表单,类似添加页面,在写好之后,点击更新分类,就会修改对应的数据表当中的数据,点击更新分类,前端页面就会提交表单到路由函数update_category中,此时请求方式就是POST请求,然后通过request获取对应的数据,再查询数据表得到对应的数据对象,替换其字段的值即可完成修改,修改完成后,重定向刷新页面。


总结:

  • 1、项目框架确定后,搭建项目时,一定要注意修改模板,如果有多个视图函数,还得在init中创建对应数量的蓝图。
  • 2、展示页面的前后端数据交互相对简单。
  • 3、后台管理页面,实现增删改查有对应模板套用即可,单删除操作相对复杂。
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值