人员管理创建

pear-flask-admin二次开发

Posted by Carlos on May 6, 2022

本文主要解释关于二次开发实际的操作步骤,并附上一些演示代码

1.models表单创建

这部分代码定义了一个名为UsersModel的模型类,用于管理用户信息。模型类中包含了以下字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
class UsersModel(db.Model):
    '''用户管理'''
    __tablename__ = 'tr_users'
    id = db.Column(db.Integer, primary_key=True, comment="用户ID")
    username = db.Column(db.String(100), unique=True, nullable=False, comment="用户名")
    role = db.Column(db.String(100), comment="角色")
    contact = db.Column(db.String(100), nullable=True, comment="联系方式") #nullable=True非必填项
    photo = db.Column(db.String(255), comment="照片或者身份证") #仅存储上传照片名称
    created_at = db.Column(db.DateTime, default=datetime.utcnow, comment="创建时间")
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, comment="更新时间")

    def __repr__(self):
        return f"<UserModel {self.username}>"

2.view 视图函数创建 view/Trops_view/users

这部分代码定义了一个名为Trips_Users_info的视图函数,用于处理用户列表页面的请求。该函数被装饰器@index_bp.get(‘/Trips/Users/info’)修饰,表示该函数处理/Trips/Users/info路径的GET请求。在函数内部,会渲染名为Trips/Users/users_info.html的模板文件并返回。

1
2
3
4
5
6
# 用户列表
@index_bp.get('/Trips/Users/info') # 经过index.py 封装了一层的 @app.route('/')方法
@view_logging_required # 中间件判断是否登录
@permission_required('tr:user:info') #角色赋权会用到 根据标识管理功能权限保证值是一样的
def Trips_Users_info():
    return render_template('Trips/Users/users_info.html')


3.添加代码视图函数

这部分代码是一个HTML模板文件,用于生成用户列表页面。页面中包含一个表格,使用Layui的Table组件进行展示。具体表格的列定义、数据解析和渲染等操作使用JavaScript进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<head>
    <title>游玩人员管理</title>
    {% include 'admin/common/header.html' %}
    <link rel="stylesheet" href="/static/admin/admin/css/other/user.css"/>
</head>
<body class="pear-container">

{# 用户表格 #}
<div class="user-main user-collasped">
    <div class="layui-card">
        <div class="layui-card-body">
            <table id="tables" lay-filter="tables"></table>
        </div>
    </div>
</div>


{% include 'admin/common/footer.html' %}


<script>
  // layui 初始化方法
  layui.use(['table', 'dtree', 'form', 'jquery', 'popup', 'common'], function() {
    let table = layui.table;
    let form = layui.form;
    let $ = layui.jquery;
    let dtree = layui.dtree;
    let popup = layui.popup;
    let common = layui.common;

    // 表格数据
    const get_columns = () => [
    [
        {type: 'checkbox'},
        {title: '用户ID', field: 'id', align: 'center', width: 110},
        {title: '用户名', field: 'username', align: 'center'},
        {title: '角色', field: 'role', align: 'center'},
        {title: '联系方式', field: 'contact', align: 'center'},
        {title: '照片', field: 'photo', align: 'center'},
        {title: '创建时间', field: 'created_at', align: 'center'},
        {title: '更新时间', field: 'updated_at', align: 'center'},
        {title: '操作', toolbar: '#tool', align: 'center', width: 130},
    ],
    ];


    // 渲染表格数据
    table.render({
      parseData: parserTableData,
      elem: '#tables',
      url: '/tr/v1/Trips/Users/info/',
      page: true,
      cols: get_columns(),
      skin: 'line',
      height: 'full-148',
      toolbar: '#toolbar', /*工具栏*/
      text: {none: '暂无人员信息'},
      defaultToolbar: [{layEvent: 'refresh', icon: 'layui-icon-refresh'}, 'filter', 'print', 'exports'], /*默认工具栏*/
    });


4.在applications中添加 init.py 初始化方法 初始化一个新的蓝图

这部分代码是初始化一个新的蓝图,并将其注册到Flask应用中。其中api_tr是一个名为’tr’的蓝图对象,指定了URL前缀为’/tr/v1’,表示该蓝图下的所有路由都以’/tr/v1’开头。同时,通过调用register_Trips_users_api函数注册了Trips/Users/info/路径对应的API处理函数。

1
2
3
4
5
6
7
8
9
10
'''
1.api_tr 是一个名为 'tr' 的蓝图对象。
2.定义了一个 URL 前缀为 /tr/v1 的蓝图,意味着该蓝图下的所有路由都需要以 /tr/v1 开头。
'''
api_tr : Blueprint = Blueprint('tr', __name__, url_prefix='/tr/v1')
from .Trips import register_Trips_users_api
register_Trips_users_api(api_tr)

def init_api(app: Flask) -> None:
    app.register_blueprint(api_tr)

5.在applications中添加 添加Trips文件夹,里面添加Trips_Users.py文件和init.py文件。


init.py文件:定义了register_Trips_users_api函数,用于注册Trips/Users/info/路径对应的API处理函数以及其他相关路径的处理函数。具体实现逻辑需要根据实际需要进行添加。

1
2
3
4
5
6
7
8
9
10
11
12
13
def register_Trips_users_api(api_tr):

    # 对象是class
    register_api(Trip_UsersApi, 'Trip_UsersApi', '/Trips/Users/info/', pk='_id', app=api_tr)

    #对象是method
    api_tr.add_url_rule('/Trips/Users/<int:_id>/edit',
                        view_func=Trips_users_edit,
                        methods=['PUT'])

    api_tr.add_url_rule('/Trips/Users/batch_remove',
                        view_func=batch_remove,
                        methods=['DELETE'])

trips_users.py文件:定义了一个名为Trip_UsersApi的API处理类,用于处理用户数据相关的请求。其中定义了一个QueryModel类用于查询参数的验证和处理,包括分页信息、用户名、角色、联系方式和照片等字段。在get方法中,根据查询参数进行模糊查询,并使用分页功能对结果进行返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 查询分页操作
class QueryModel(BaseModel):
    page: int = 1
    limit: int = 10

    username: t.Optional[str]
    role: t.Optional[str] 
    contact: t.Optional[str]
    photo: t.Optional[int]
    # status: t.Optional[int]

class Trip_UsersApi(MethodView):
    """用户数据"""

    @validate() #用于验证Model函数的输入参数是否符合预期的规则和条件
    def get(self, _id, query: QueryModel):

        filters = []

        # 模糊查询
        if query.role:
            filters.append(UsersModel.role.like('%' + query.role + '%'))
        if query.username:
            filters.append(UsersModel.username.like('%' + query.username + '%'))

       # 分页 排序
        paginate = UsersModel.query.filter(
            *filters).order_by(
                UsersModel.id.desc()).paginate(
                    page=query.page, per_page=query.limit, error_out=False)

        user_data = [{
            'id': item.id,
            'username': item.username,
            'role': item.role,
            'contact': item.contact,
            'photo': item.photo,
            'created_at': str(item.created_at),
            'updated_at': str(item.updated_at),
            # 'dept': dept_name(item.dept_id),
        } for item in paginate.items]

        return table_api(
            result={
                'items': user_data,
                'total': paginate.total,
            }
            , code=0
        )

6.效果图

image.png