Python学习笔记:6.3.8 第二次代码重构

这篇博客记录了在Flask中进行代码重构的过程,包括用户角色的设定(匿名用户、登录用户、管理员),利用 Blueprint.before_request 实现钩子函数进行权限控制,以及网站配置的集中管理和加载。博主分享了实操步骤,旨在提高代码的整洁性和效率。
摘要由CSDN通过智能技术生成

前言:本文是学习网易微专业的《python全栈工程师 - Flask高级建站》课程的笔记,欢迎学习交流。同时感谢老师们的精彩传授!

一、课程目标
  • 重构目标
  • 钩子函数Blueprint.before_request
  • 网站配置加载
二、详情解读
2.1.重构目标
2.1.1.用户角色

一个用户因为他的身份的不同,在网站中所具有的权限也不同,这种就称为用户角色,最简单的网站用户角色分为:匿名用户、登录用户、管理员

用户角色说明
匿名用户没有进行登录的用户,即使已经注册成为网站会员
登录用户经过登录后,赋予了会员身份的用户
管理员具有管理网站能力的登录用户
2.1.2.匿名用户行为
普通用户
浏览文章
注册
登录
2.1.3.登录用户行为

在这里插入图片描述

2.1.4.管理员行为

在这里插入图片描述

2.1.5.重构目标

1.更有效的根据用户的角色控制用户的行为

匿名用户可访问路径:
网站首页 - /
登录页面 - /login
注册页面 - /register
文章分类浏览 - /artilce/cate/
文章详细浏览 - /article/view/

2.登录用户可以访问匿名用户访问的所有页面

登录用户可访问路径:
注册信息修改 - /member/info/edit
文章发布 - /memeber/article/add
文章管理 - /member/article/list
文章删除 - /member/article/delete
文章修改 - /member/article/edit

3.管理员用户可以访问匿名用户访问的所有页面,管理员角色与普通会员并不相同,一般不需要拥有进入普通会员相关页面

管理员可访问路径:
会员管理 - /admin/user/list/admin/user/edit/admin/user/delete
文章管理 - /admin/article/list/admin/article/add
分类管理 - /admin/cate/list/admin/cate/add/admin/cate/edit/admin/cate/delete

2.2.代码调整
2.2.1.代码调整 - 后台管理

新增admin目录,所有与管理员操作相关的视图函数移到此目录下。后台管理有专用的后台界面
在这里插入图片描述

2.2.1.代码调整 - 会员中心

新增member目录和,所有会员操作相关的视图函数移到此目录下。会员中心有专用的界面
在这里插入图片描述
实操1:后台管理部分
Step1:在项目目录下,新建admin目录,并新建admin_app.py文件,写入以下代码:

# -*- coding=utf-8 -*-
from flask import request, session, redirect, url_for, render_template
from flask import Blueprint
from libs import login_required

admin_app = Blueprint('admin_app', __name__)

# before_request钩子函数的作用:
# 当请求进来的时候,首先执行下面的is_admin()函数
# 只要访问admin_app,就会检查是否已经登录
@admin_app.before_request
@login_required
def is_admin():
    print(session['user'])
    if session['user'] != 'admin':
        return redirect(url_for('login'))

@admin_app.route('/')
def admin_index():
    return render_template('admin/admin_index.html')

Step2:新建admin/article.py文件,写入以下代码:

# -*- coding=utf-8 -*-
from flask import request, session, render_template, redirect, url_for

from .admin_app import admin_app
from models import Article, Category
from libs import db
import json

@admin_app.route('/article/post', methods=['GET', 'POST'])
def article_post():
    if request.method == 'POST':
        cate_id = request.form['cate']
        title = request.form['title']
        intro = request.form['intro']
        content = request.form['content']
        article = Article(
            cate_id = cate_id,
            title = title,
            intro = intro,
            content = content,
            author = session['user']
        )
        message = None
        try:
            db.session.add(article)
            db.session.commit()
            message = {'message': '发布成功'}
        except Exception as e:
            db.session.rollback()
            message = {'message': str(e)}
        return json.dumps(message)
    return render_template('admin/article/article_post.html')

# 获得文章列表
@admin_app.route('/article/list/<int:page>', methods=['GET', 'POST'])
@admin_app.route('/article/list', default={'page': 1}, methods=['GET', 'POST'])
def article_list(page):
    if request.method == 'POST':
        q = request.form['q']
        condition = { request.form['field']: q}
        if request.form['field'] == 'title':
            condition = Article.title.like('%%%s%%' % q)
        else:
            condition = Article.content.like('%%%s%%' % q)

        if request.form['order'] == '1':
            order = Article.id.asc()
        else:
            order = Article.id.desc()

        res = Article.query.filter(condition).order_by(order).paginate(page, 10)

    else:
        res = Article.query.paginate(page, 10)

    # 无论搜索还是默认查看,都是翻页处理
    articles = res.items
    pageList = res.iter_pages()

    return render_template('admin/article/article_list.html', articles = articles,
                           pageList = pageList
                           )

# 根据文章id删除文章
@admin_app.route('/article/delete/<int:article_id>')
def article_delete(article_id):
    article = Article.query.get(article_id)
    db.session.delete(article)
    db.session.commit()
    return redirect(url_for('.article_list'))

# 文章修改
@admin_app.route('/article/edit/<int:article_id>', methods=['GET', 'POST'])
def article_edit(article_id):
    article = Article.query.get(article_id)
    if request.form == 'POST':
        article.cate_id = request.form['cate']
        article.title = request.form['title']
        article.intro = request.form['intro']
        article.content = request.form['content']
        db.session.commit()
        return redirect(url_for('.article_list'))
    return render_template('admin/article/article_edit.html', article = article)

Step3:新建admin/category.py文件,写入以下代码:

# -*- coding=utf-8 -*-
from flask import request, session, render_template, redirect, url_for

from .admin_app import admin_app
from models import Article, Category
from libs import db
import json

#分类视图部分
# 添加分类
@admin_app.route('/category/add_cate', methods=['GET', 'POST'])
def addCate():
    message = None
    if request.method == 'POST':
        cate_name = request.form['name']
        cate_order = request.form['order']
        category = Category(
            cate_name = cate_name,
            cate_order = cate_order
        )
        try:
            db.session.add(category)
            db.session.commit()
            message = '分类添加成功'
        except Exception as e:
            db.session.rollbck()
            message = '发生了错误:' + str(e)
    return render_template('amdin/category/category_add.html', message=message)

# 获得分类列表
@admin_app.route('/category/cate_list')
def cateList():
    cates = Category.query.order_by(Category.cate_order.desc()).all()
    return render_template('admin/category/category_list.html', cates=cates)

# 删除分类
@admin_app.route('/category/cate_delete/<int:cate_id>')
def deleteCate(cate_id):
    cate = Category.query.get(cate_id)
    db.session.delete(cate)
    db.session.commit()
    return render_template('admin/category/category_list.html')

# 分类修改
@admin_app.route('/cate_edit/<int:cate_id>', methods=['GET', 'POST'])
def editCate(cate_id):
    category = Category.query.get(cate_id)
    if request.method == 'POST':
        category.cate_name = request.form['name']
        category.cate_order = request.form['order']
        db.session.commit()
        return redirect(url_for('.cateList'))
    return render_template('category/edit.html', category=category)

Step4:新建admin/user.py文件,写入以下代码:

# -*- coding=utf-8 -*-
from flask import request, session, render_template, redirect, url_for

from .admin_app import admin_app
from models import User
from libs import db
import json

# 验证用户名是否重复
def validate_username(username):
    return User.query.filter_by(username=username).first()

# 获得用户列表
# 如果用户刚进入列表页是访问http://127.0.0.1/user/list
# 与“/list/<int:page>"不匹配,提供一个默认带有page默认值的路由

@admin_app.route('/user/list/<int:page>', methods=['GET', 'POST'])
@admin_app.route('/user/list', defaults={'page': 1}, methods=['GET', 'POST'])
def userList(page):
    if request.method == 'POST':
        q = request.form['q']
        condition = { request.form['field']: q}
        if request.form['field'] == 'realname':
            condition  = User.realname.like('%%%s%%' % q)
        else:
            condition = User.username.like('%%%s%%' % q)
        if request.form['order'] == '1':
            order = User.id.asc()
        else:
            order = User.id.desc()

        res = User.query.filter_by(condition, User.sex==request.form['sex']).order_by(order).paginate(page, 10)
    else:
        res = User.query.paginate(page, 10)
    #无论搜索还是默认查看,都是翻页处理
    users = res.items
    pageList = res.iter_pages()

    return render_template('admin/user_list.html', users=users,
                           pageList=pageList,
                           page=res.pages,
                           total=res.total
                           )

# 根据用户id删除用户
@admin_app.route('/delete/<int:user_id>')
def deleteUser(user_id):
    user = User.query.get(user_id)
    db.session.delete(user)
    db.session.commit()
    return redirect(url_for('.userList'))

# 用户信息修改
@admin_app.route('/user/edit/<int:user_id>', methods=['GET', 'POST'])
def editUser(user_id):
    user = User.query.get(user_id)
    if request.method == 'POST':
        user.username = request.form['username']
        user.realname = request.form['name']
        user.sex = request.form['sex']
        user.mylike = '|'.join(request.form.getlist('like'))
        user.city = request.form['city']
        user.intro = request.form['intro']
        db.session.commit()
        return redirect(url_for('.userList'))
    return render_template('admin/user/user_edit.html', user=user)

Step5:新建admin/__init__.py文件,写入以下代码:

from .admin_app import admin_app, admin_index, is_admin
from .article import *
from .category import *
from .user import *

实操2:会员中心部分
Step1:在项目目录下,新建member目录,并新建member_app.py文件,写入以下代码:

# -*- coding=utf-8 -*-
from flask import request, session, redirect, session, url_for, render_template
from flask import Blueprint
from libs import login_required

member_app = Blueprint('member_app', __name__)

@member_app.before_request
@login_required
def is_login():
    print(session['user'])

@member_app.route('/')
def member_index():
    print('hello')
    return render_template('member/member_index.html')

Step2:新建member/article.py文件,写入以下代码:

# -*- coding=utf-8 -*-
from flask import request, session, render_template, redirect, url_for

from .member_app import member_app
from models import Article, Category
from libs import db
import json

@member_app.route('/article/post', methods=['GET', 'POST'])
def article_post():
    if request.method == 'POST':
        cate_id = request.form['cate']
        title = request.form['title']
        intro = request.form['intro']
        content = request.form['content']
        article = Article(
            cate_id = cate_id,
            title = title,
            intro = intro,
            content = content,
            author = session['user']
        )
        message = None
        try:
            db.session.add(article)
            db.session.commit()
            message = {'message': '发布成功'}
        except Exception as e:
            db.session.rollback()
            message = {'message': str(e)}
        return json.dumps(message)
    return render_template('member/article/article_post.html')

# 获得文章列表
@member_app.route('/article/list/<int:page>', methods=['GET', 'POST'])
@member_app.route('/article/list', defaults={'page': 1}, methods=['GET', 'POST'])
def article_list(page):
    if request.method == 'POST':
        q = request.form['q']
        condition = { request.form['field']: q}
        if request.form['field'] == 'title':
            condition = Article.title.like('%%%s%%' % q)
        else:
            condition = Article.content.like('%%%s%%' % q)

        if request.form['order'] == '1':
            order = Article.id.asc()
        else:
            order = Article.id.desc()

        res = Article.query.filter(Article.author == session['user']).filter(condition).order_by(order).paginate(page, 10)

    else:
        res = Article.query.filter(Article.author == session['user']).paginate(page, 10)

    # 无论搜索还是默认查看,都是翻页处理
    articles = res.items
    pageList = res.iter_pages()

    return render_template('member/article/article_list.html', articles = articles,
                           pageList = pageList
                           )

# 根据文章id删除文章
@member_app.route('/article/delete/<int:article_id>')
def article_delete(article_id):
    article = Article.query.get(article_id)
    # 只能删除自己的文章
    if article.author == session['user']:
        db.session.delete(article)
        db.session.commit()
    return redirect(url_for('.article_list'))

# 文章修改
@member_app.route('/article/edit/<int:article_id>', methods=['GET', 'POST'])
def article_edit(article_id):
    article = Article.query.get(article_id)
    if request.form == 'POST':
        # 只能修改自己的文章
        if article.author == session['user']:
            article.cate_id = request.form['cate']
            article.title = request.form['title']
            article.intro = request.form['intro']
            article.content = request.form['content']
            db.session.commit()
            return redirect(url_for('.article_list'))
    return render_template('member/article/article_edit.html', article = article)

Step3:新建member/user.py文件,写入以下代码:

# -*- coding=utf-8 -*-
from flask import request, session, render_template, redirect, url_for

from .member_app import member_app
from models import User
from libs import db
import json

# 用户信息修改
@member_app.route('/user/Edit', methods=['GET', 'POST'])
def userEdit():
    # 普通会员只能修改自己的资料
    # 修改资料的时候还需要验证密码
    user = User.query.filter_by(username=session['user']).one()
    if request.method == 'POST':
        user.username = request.form['username']
        user.realname = request.form['name']
        user.sex = request.form['sex']
        user.mylike = '|'.join(request.form.getlist('like'))
        user.city = request.form['city']
        user.intro = request.form['intro']
        db.session.commit()
    return render_template('member/info/info_edit.html', user=user)

Step3:新建member/__init__.py文件,写入以下代码:

# -*- coding=utf-8 -*-
from .member_app import member_app, is_login, member_index

from .article import *
from .user import *

Step4:在app.py中引入admin_appmember_app并注册蓝印:

.
.
.
from flask import session
# 新增下面这两行
from admin import admin_app
from member import member_app
.
.
.
app.register_blueprint(upload_app, url_prefix="/upload")
# 新增下面这两行
app.register_blueprint(admin_app, url_prefix="/admin")
app.register_blueprint(member_app, url_prefix="/member")
.
.
.
2.3.钩子函数before_request
2.3.1.Blueprint.before_request

通过before_request装饰的函数是在request被视图处理之前就会执行,因此我们可以在蓝印实例上,使用此装饰函数,这样就避免在每一个需要验证身份的视图函数上通过@login_required装饰

@admin_app.before_request
@login_required
def is_admin():
	pass
2.4.网站配置加载
2.41.网站配置

随着网站的功能越来越多,网站的各种参数配置也在增加,可以在一个文件里专门配置各类参数,然后通过在app.py中加载参数,从而提高代码的整洁性。

增加配置文件settings.py,通过app.config.from_object(配置对象)方式加载。

实操3:
Step1:在项目目录下,新建settings.py文件,写入以下代码:

# -*- coding=utf-8 -*-

class BaseConfig:
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    SQLALCHEMY_DATABASE_URI = "sqlite:///my.db"
    ALLOW_UPLOAD_TYPE = ["image/jpeg", "image/png", "image/gif"]
    SECRET_KEY = "123456"

class DevelopmentConfig(BaseConfig):
    pass

class ProductionConfig(BaseConfig):
    pass

config = {
    'development': DevelopmentConfig,
    'produciton': ProductionConfig
}

Step2:修改app.py文件:

.
.
.
from member import member_app
# 新增下面这一行
from settings import config

app = Flask(__name__)

# 将下面这四个配置删除,因为配置已经移到settings.py文件了
# app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///my.db"
# app.config['ALLOW_UPLOAD_TYPE'] = ["image/gif", "image/png", "image/jpg", "image/jpeg"]
# app.secret_key = "123456"

# 新增下面这一行,这里表示加载开发环境的配置
app.config.from_object(config['development'])
.
.
.
三、课程小结:
  • 用户角色
    实现用户角色管理,需要通过代码重构来实现。
  • 代码重构
  • 配置加载
    通过配置加载,可以根据不同的环境加载不同的配置
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值