refactor(api):前后端半分离

This commit is contained in:
zhengxinonly
2021-07-21 02:19:52 +08:00
parent c26f15ae69
commit 5470837707
26 changed files with 338 additions and 364 deletions
+19 -11
View File
@@ -1,13 +1,21 @@
from applications.view.system import register_system_views
from applications.view.index import register_index_views
from applications.view.passport import register_passport_views
from applications.view.rights import register_rights_view
from applications.view.department import register_dept_views
from flask import Flask
from .department import dept_bp
from .file import file_bp
from .index import index_bp
from .logs_view import logs_bp
from .passport import passport_bp
from .rights import rights_bp
from .roles import role_bp
from .users import users_bp
def init_view(app):
register_system_views(app)
register_index_views(app)
register_rights_view(app)
register_passport_views(app)
register_dept_views(app)
def init_view(app: Flask):
app.register_blueprint(dept_bp)
app.register_blueprint(file_bp)
app.register_blueprint(index_bp)
app.register_blueprint(logs_bp)
app.register_blueprint(passport_bp)
app.register_blueprint(rights_bp)
app.register_blueprint(role_bp)
app.register_blueprint(users_bp)
-4
View File
@@ -11,10 +11,6 @@ dept_bp = Blueprint('dept', __name__, url_prefix='/dept')
dept_api = Api(dept_bp)
def register_dept_views(app):
app.register_blueprint(dept_bp)
@dept_bp.get('/')
@authorize("admin:dept:main", log=True)
def main():
+51
View File
@@ -0,0 +1,51 @@
import os
from flask import Blueprint, request, render_template, current_app
from flask_restful import marshal
from sqlalchemy import desc
from applications.common.serialization import photo_fields
from applications.common.utils.http import table_api, success_api, fail_api
from applications.common.utils.rights import authorize
from applications.extensions import db
from applications.models import Photo
file_bp = Blueprint('file', __name__, url_prefix='/file')
# 图片管理
@file_bp.get('/')
@authorize("admin:file:main", log=True)
def index():
return render_template('admin/file/photo.html')
# 图片数据
@file_bp.get('/table')
@authorize("admin:file:main", log=True)
def table():
page = request.args.get('page', type=int)
limit = request.args.get('limit', type=int)
photo_paginate = Photo.query.order_by(desc(Photo.create_time)).paginate(page=page, per_page=limit, error_out=False)
data = marshal(photo_paginate.items, photo_fields)
return table_api(data=data, count=photo_paginate.total)
# 图片批量删除
@file_bp.route('/batchRemove', methods=['GET', 'POST'])
@authorize("admin:file:delete", log=True)
def batch_remove():
ids = request.form.getlist('ids[]')
photo_name = Photo.query.filter(Photo.id.in_(ids)).all()
upload_url = current_app.config.get("UPLOADED_PHOTOS_DEST")
for p in photo_name:
os.remove(upload_url + '/' + p.name)
photo = Photo.query.filter(Photo.id.in_(ids)).delete(synchronize_session=False)
db.session.commit()
if photo:
return success_api(msg="删除成功")
else:
return fail_api(msg="删除失败")
from . import file
+8 -47
View File
@@ -1,43 +1,19 @@
import os
from flask import Blueprint, request, render_template, jsonify, current_app, make_response
from flask_restful import Api, Resource, marshal
from sqlalchemy import desc
from flask import request, jsonify
from flask_restful import Api, Resource
from applications.common.serialization import photo_fields
from applications.common.utils.http import fail_api, success_api, table_api
from applications.common.utils.http import fail_api, success_api
from applications.common.utils.rights import authorize
from applications.extensions import db
from applications.models import Photo
from applications.view.file import file_bp
from applications.view.file._utils import upload_one, delete_photo_by_id
from applications.view.file._utils import delete_photo_by_id, upload_one
file_bp = Blueprint('file', __name__, url_prefix='/file')
file_api = Api(file_bp)
# 图片管理
@file_bp.get('/')
@authorize("admin:file:main", log=True)
def index():
return render_template('admin/file/photo.html')
# 图片数据
@file_bp.get('/table')
@authorize("admin:file:main", log=True)
def table():
page = request.args.get('page', type=int)
limit = request.args.get('limit', type=int)
photo_paginate = Photo.query.order_by(desc(Photo.create_time)).paginate(page=page, per_page=limit, error_out=False)
data = marshal(photo_paginate.items, photo_fields)
return table_api(data=data, count=photo_paginate.total)
@file_api.resource('/upload')
class Upload(Resource):
@authorize("admin:file:add", log=True)
def get(self):
return make_response(render_template('admin/file/photo_add.html'))
# @authorize("admin:file:add", log=True)
# def get(self):
# return make_response(render_template('admin/file/photo_add.html'))
@authorize("admin:file:add", log=True)
def post(self):
@@ -66,18 +42,3 @@ class Upload(Resource):
return fail_api(msg="删除失败")
# 图片批量删除
@file_bp.route('/batchRemove', methods=['GET', 'POST'])
@authorize("admin:file:delete", log=True)
def batch_remove():
ids = request.form.getlist('ids[]')
photo_name = Photo.query.filter(Photo.id.in_(ids)).all()
upload_url = current_app.config.get("UPLOADED_PHOTOS_DEST")
for p in photo_name:
os.remove(upload_url + '/' + p.name)
photo = Photo.query.filter(Photo.id.in_(ids)).delete(synchronize_session=False)
db.session.commit()
if photo:
return success_api(msg="删除成功")
else:
return fail_api(msg="删除失败")
+18 -8
View File
@@ -1,14 +1,24 @@
from flask import Blueprint
from flask import render_template
from flask_login import login_required, current_user
index_bp = Blueprint('index', __name__, url_prefix='/')
from . import index
index_bp = Blueprint('index', __name__)
def register_index_views(app):
"""
初始化蓝图
@index_bp.route('/')
def index():
return render_template('index/index.html')
"""
app.register_blueprint(index_bp)
# 首页
@index_bp.get('/admin')
@login_required
def admin_index():
return render_template('admin/index.html', user=current_user)
# 控制台页面
@index_bp.get('/admin/welcome')
@login_required
def welcome():
return render_template('admin/console/welcome.html')
-8
View File
@@ -1,8 +0,0 @@
from flask import render_template
from . import index_bp
@index_bp.route('/')
def index():
return render_template('index/index.html')
@@ -7,16 +7,16 @@ from applications.common.utils.http import table_api
from applications.common.utils.rights import authorize
from applications.models import AdminLog
admin_log = Blueprint('logs', __name__, url_prefix='/logs')
logs_bp = Blueprint('logs', __name__, url_prefix='/logs')
@admin_log.get('/')
@logs_bp.get('/')
@authorize("admin:log:main")
def index():
return render_template('admin/admin_log/main.html')
@admin_log.get('/login_log')
@logs_bp.get('/login_log')
@authorize("admin:log:main")
def login_log():
page = request.args.get('page', type=int)
@@ -30,7 +30,7 @@ def login_log():
return table_api(data=data, count=log_paginate.total)
@admin_log.get('/access_log')
@logs_bp.get('/access_log')
@authorize("admin:log:main")
def operate_log():
page = request.args.get('page', type=int)
+7 -52
View File
@@ -1,17 +1,10 @@
from flask import Blueprint, session, redirect, url_for, render_template, request, make_response
from flask_login import current_user, login_user, login_required, logout_user
from flask_restful import Resource, Api, reqparse
from applications.common.admin_log import login_log
from applications.common.utils.http import fail_api, success_api
from applications.models import User
from flask import Blueprint, session
from flask_login import login_required, logout_user
from applications.common.utils.http import success_api
from ._utils import get_captcha_image, add_auth_session
passport_bp = Blueprint('passport', __name__, url_prefix='/passport')
passport_api = Api(passport_bp)
def register_passport_views(app):
app.register_blueprint(passport_bp)
# 获取验证码
@@ -22,47 +15,6 @@ def get_captcha():
return resp
@passport_api.resource('/login')
class Login(Resource):
login_req = reqparse.RequestParser(bundle_errors=True)
login_req.add_argument('username', type=str, help='请输入用户名', required=True)
login_req.add_argument('password', type=str, help='请输入密码', required=True)
login_req.add_argument('captcha', type=str, help='请输入验证码', required=True)
def get(self):
if current_user.is_authenticated:
return redirect(url_for('admin.index'))
return make_response(render_template('admin/login.html'))
def post(self):
req = self.login_req.parse_args()
s_code = session.get("code", None)
if req.captcha != s_code:
return fail_api(msg="验证码错误")
user = User.query.filter_by(username=req.username).first()
if user is None:
return fail_api(msg="不存在的用户")
if user.enable is 0:
return fail_api(msg="用户被暂停使用")
if user.validate_password(req.password):
# 登录
login_user(user)
# 记录登录日志
login_log(request, uid=user.id, is_access=True)
# 存入权限
add_auth_session()
return success_api(msg="登录成功")
login_log(request, uid=user.id, is_access=False)
return fail_api(msg="用户名或密码错误")
# 退出登录
@passport_bp.post('/logout')
@login_required
@@ -70,3 +22,6 @@ def logout():
logout_user()
session.pop('permissions')
return success_api(msg="注销成功")
from . import api
+53
View File
@@ -0,0 +1,53 @@
from flask import session, redirect, url_for, request
from flask_login import current_user, login_user
from flask_restful import Resource, reqparse, Api
from applications.common.admin_log import login_log
from applications.common.utils.http import fail_api, success_api
from applications.models import User
from . import passport_bp
from ._utils import add_auth_session
from flask import render_template, make_response
passport_api = Api(passport_bp)
@passport_api.resource('/login')
class Login(Resource):
login_req = reqparse.RequestParser(bundle_errors=True)
login_req.add_argument('username', type=str, help='请输入用户名', required=True)
login_req.add_argument('password', type=str, help='请输入密码', required=True)
login_req.add_argument('captcha', type=str, help='请输入验证码', required=True)
def get(self):
if current_user.is_authenticated:
return redirect(url_for('admin.index'))
# TODO 分离视图操作 最终实现接口登录与视图登录两套逻辑
return make_response(render_template('admin/login.html'))
def post(self):
req = self.login_req.parse_args()
s_code = session.get("code", None)
if req.captcha != s_code:
return fail_api(msg="验证码错误")
user = User.query.filter_by(username=req.username).first()
if user is None:
return fail_api(msg="不存在的用户")
if user.enable is 0:
return fail_api(msg="用户被暂停使用")
if user.validate_password(req.password):
# 登录
login_user(user)
# 记录登录日志
login_log(request, uid=user.id, is_access=True)
# 存入权限
add_auth_session()
return success_api(msg="登录成功")
login_log(request, uid=user.id, is_access=False)
return fail_api(msg="用户名或密码错误")
+10 -5
View File
@@ -1,12 +1,17 @@
from flask import Blueprint, Flask
from flask import Blueprint, render_template
from flask_restful import Api
from ...common.utils.rights import authorize
rights_bp = Blueprint('rights', __name__, url_prefix='/rights')
rights_api = Api(rights_bp)
@rights_bp.get('/')
@authorize("admin:power:main", log=True)
def index():
return render_template('admin/rights/main.html')
from . import routes
from . import right
def register_rights_view(app: Flask):
app.register_blueprint(rights_bp)
+4 -7
View File
@@ -1,4 +1,4 @@
from flask import render_template, request, jsonify, make_response
from flask import request, jsonify
from flask_restful import Resource, reqparse
from . import rights_bp, rights_api
@@ -8,6 +8,9 @@ from ...common.utils.rights import authorize
from ...extensions import db
from ...models import Power, Role
# TODO 分离视图操作
from flask import render_template, make_response
parser_power = reqparse.RequestParser(bundle_errors=True)
parser_power.add_argument('icon', type=str)
parser_power.add_argument('openType', type=str, dest='open_type')
@@ -19,12 +22,6 @@ parser_power.add_argument('powerUrl', type=str, dest='power_url')
parser_power.add_argument('sort', type=int, dest='sort')
@rights_bp.get('/')
@authorize("admin:power:main", log=True)
def index():
return render_template('admin/rights/main.html')
@rights_bp.get('/data')
@authorize("admin:power:main", log=True)
def data():
+24
View File
@@ -0,0 +1,24 @@
from flask import Blueprint, render_template
from applications.common.utils.rights import authorize
from applications.view.roles._utils import remove_role, batch_remove_role
role_bp = Blueprint('role', __name__, url_prefix='/admin/role')
# 角色而管理
@role_bp.get('/')
@authorize("admin:role:main", log=True)
def main():
return render_template('admin/role/main.html')
# 角色授权操作
@role_bp.get('/power/<int:_id>')
@authorize("admin:role:power", log=True)
def power(_id):
return render_template('admin/role/power.html', id=_id)
from . import role
+6 -6
View File
@@ -2,9 +2,9 @@ from applications.extensions import db
from applications.models import Power, Role, User
def remove_role(_id):
def remove_role(role_id):
""" 删除角色 """
role = Role.query.filter_by(id=_id).first()
role = Role.query.filter_by(id=role_id).first()
# 删除该角色的权限
power_id_list = []
for p in role.power:
@@ -19,12 +19,12 @@ def remove_role(_id):
users = User.query.filter(User.id.in_(user_id_list)).all()
for u in users:
role.user.remove(u)
r = Role.query.filter_by(id=_id).delete()
r = Role.query.filter_by(id=role_id).delete()
db.session.commit()
return r
def batch_remove_role(ids):
def batch_remove_role(role_ids):
""" 批量删除 """
for _id in ids:
remove_role(_id)
for role_id in role_ids:
remove_role(role_id)
+7 -21
View File
@@ -1,29 +1,22 @@
from flask import Blueprint, render_template, jsonify, make_response
from flask import jsonify
from flask_login import login_required
from flask_restful import Resource, Api, reqparse
from flask_restful import Resource, Api, reqparse, marshal
from applications.extensions import db
from applications.models import Role, Power
from applications.common.utils.http import table_api, success_api, fail_api
from applications.common.utils.rights import authorize
from flask_restful import reqparse, marshal
from applications.common.serialization import power_fields
from applications.view.roles._utils import remove_role, batch_remove_role
from . import role_bp
from ._utils import remove_role, batch_remove_role
# TODO 分离视图操作
from flask import render_template, make_response
role_bp = Blueprint('role', __name__, url_prefix='/admin/role')
role_api = Api(role_bp)
# 角色而管理
@role_bp.get('/')
@authorize("admin:role:main", log=True)
def main():
return render_template('admin/role/main.html')
# 表格数据
@role_bp.get('/data')
@authorize("admin:role:main", log=True)
@@ -87,13 +80,6 @@ class AddRole(Resource):
return success_api(msg="成功")
# 角色授权操作
@role_bp.get('/power/<int:_id>')
@authorize("admin:role:power", log=True)
def power(_id):
return render_template('admin/role/power.html', id=_id)
@role_api.resource('/role_power/<int:role_id>')
class RolePower(Resource):
-15
View File
@@ -1,15 +0,0 @@
from flask import Flask
from applications.view.system.logs import admin_log
from applications.view.system.index import admin_bp
from applications.view.file.file import file_bp
from applications.view.roles.role import role_bp
from applications.view.users import users_bp
def register_system_views(app: Flask):
app.register_blueprint(admin_bp)
app.register_blueprint(users_bp)
app.register_blueprint(file_bp)
app.register_blueprint(admin_log)
app.register_blueprint(role_bp)
-19
View File
@@ -1,19 +0,0 @@
from flask import Blueprint, render_template
from flask_login import login_required, current_user
admin_bp = Blueprint('admin', __name__, url_prefix='/admin')
# 首页
@admin_bp.get('/')
@login_required
def index():
user = current_user
return render_template('admin/index.html', user=user)
# 控制台页面
@admin_bp.get('/welcome')
@login_required
def welcome():
return render_template('admin/console/welcome.html')
+14 -45
View File
@@ -1,52 +1,12 @@
from flask import Blueprint, request, render_template
from flask_restful import Api, reqparse
from flask import Blueprint, render_template
from flask_login import login_required, current_user
from flask_restful import Api
from sqlalchemy import desc
from applications.common.utils.http import table_api
from applications.common.utils.rights import authorize
from applications.models import Role, User, Dept
from ...models import AdminLog
users_bp = Blueprint('users', __name__, url_prefix='/users')
user_api = Api(users_bp)
# 用户分页查询
@users_bp.get('/data')
@authorize("admin:user:main", log=True)
def data():
parser = reqparse.RequestParser()
parser.add_argument('page', type=int, default=1)
parser.add_argument('limit', type=int, default=10)
parser.add_argument('realName', type=str, dest='real_name')
parser.add_argument('username', type=str)
parser.add_argument('deptId', type=int, dest='dept_id', default=0)
res = parser.parse_args()
filters = []
if res.real_name:
filters.append(User.realname.like('%' + res.real_name + '%'))
if res.username:
filters.append(User.username.like('%' + res.username + '%'))
if res.dept_id:
filters.append(User.dept_id == res.dept_id)
paginate = User.query.filter(*filters).paginate(page=res.page,
per_page=res.limit,
error_out=False)
dept_name = lambda dept_id: Dept.query.filter_by(id=dept_id).first().dept_name
user_data = [{
'id': item.id,
'username': item.username,
'realname': item.realname,
'enable': item.enable,
'create_at': item.create_at,
'update_at': item.update_at,
'dept': dept_name(item.dept_id),
} for item in paginate.items]
return table_api(data=user_data, count=paginate.total)
# 用户增加
@@ -56,5 +16,14 @@ def get():
return render_template('admin/user/main.html')
@users_bp.get('/center')
@login_required
def center():
user_logs = AdminLog.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
desc(AdminLog.create_time)).limit(10)
return render_template('admin/user/profile.html', user_info=current_user, user_logs=user_logs)
user_api = Api(users_bp)
from . import profile, _utils
from . import user_view
+4 -12
View File
@@ -1,22 +1,15 @@
# 个人中心
from flask import render_template, request, make_response, jsonify
from flask import request, jsonify
from flask_login import login_required, current_user
from flask_restful import Resource, reqparse
from sqlalchemy import desc
from applications.common.utils.http import fail_api, success_api
from applications.extensions import db
from applications.models import User, AdminLog
from applications.models import User
from applications.view.users import users_bp, user_api
@users_bp.get('/center')
@login_required
def center():
user_info = current_user
user_logs = AdminLog.query.filter_by(url='/passport/login').filter_by(uid=current_user.id).order_by(
desc(AdminLog.create_time)).limit(10)
return render_template('admin/user/profile.html', user_info=user_info, user_logs=user_logs)
# TODO 分离视图操作
from flask import render_template, make_response
@user_api.resource('/avatar')
@@ -39,7 +32,6 @@ class Avatar(Resource):
@users_bp.put('/updateInfo')
@login_required
def update_info():
parser = reqparse.RequestParser()
parser.add_argument('realname', type=str, dest='real_name')
parser.add_argument('remark', type=str)
+45 -3
View File
@@ -1,12 +1,15 @@
from flask import render_template, request, make_response
from flask import request
from flask_restful import Resource, reqparse
from applications.extensions import db
from applications.common.utils.http import fail_api, success_api
from applications.common.utils.http import fail_api, success_api, table_api
from applications.common.utils.rights import authorize
from applications.models import User, Role
from applications.models import User, Role, Dept
from applications.view.users import user_api, users_bp, _utils
# TODO 分离视图操作
from flask import render_template, make_response
@user_api.resource('/add')
class Users(Resource):
@@ -127,3 +130,42 @@ def user_enable():
else:
return fail_api(msg="出错啦")
return message
@users_bp.get('/data')
@authorize("admin:user:main", log=True)
def data():
parser = reqparse.RequestParser()
parser.add_argument('page', type=int, default=1)
parser.add_argument('limit', type=int, default=10)
parser.add_argument('realName', type=str, dest='real_name')
parser.add_argument('username', type=str)
parser.add_argument('deptId', type=int, dest='dept_id', default=0)
res = parser.parse_args()
filters = []
if res.real_name:
filters.append(User.realname.like('%' + res.real_name + '%'))
if res.username:
filters.append(User.username.like('%' + res.username + '%'))
if res.dept_id:
filters.append(User.dept_id == res.dept_id)
paginate = User.query.filter(*filters).paginate(page=res.page,
per_page=res.limit,
error_out=False)
dept_name = lambda dept_id: Dept.query.filter_by(id=dept_id).first().dept_name
user_data = [{
'id': item.id,
'username': item.username,
'realname': item.realname,
'enable': item.enable,
'create_at': item.create_at,
'update_at': item.update_at,
'dept': dept_name(item.dept_id),
} for item in paginate.items]
return table_api(data=user_data, count=paginate.total)