【tornado】系列项目之基于领域驱动模型的区域后台管理+前端easyui实现

本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站。本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用。本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采用跳转方式修改,详见博主后续博文。

后台界面展示:

地区管理包含省市县的管理。详见下文。

一、数据库设计

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
class  Province(Base):
     """
    
     """
     __tablename__  =  'province'
     nid  =  Column(Integer, primary_key = True )
     caption  =  Column(VARCHAR( 16 ), index = True )
 
 
class  City(Base):
     """
    
     """
     __tablename__  =  'city'
     nid  =  Column(Integer, primary_key = True )
     caption  =  Column(VARCHAR( 16 ), index = True )
     province_id  =  Column(Integer, ForeignKey( 'province.nid' ))
 
 
class  County(Base):
     """
     县(区)
     """
     __tablename__  =  'county'
     nid  =  Column(Integer, primary_key = True )
     caption  =  Column(VARCHAR( 16 ), index = True )
     city_id  =  Column(Integer, ForeignKey( 'city.nid' ))

  本次采用的是sqlAlchemy模块创建数据库,关于sqlAlchemy的数据库链接以及数据库创建本文不做介绍,详细见Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy(点击进入详细介绍)

表关系分析:上述表关系比较简单,市中有外键,代表这是市是属于哪个省;同理县中也有外键,代表这个县是属于哪个市。

二、目录结构

该目录结构在前面博文【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台 中有详细介绍,本博文不再赘述。

三、路由映射

1
2
3
4
5
6
(r "/ProvinceManager.html$" , Region.ProvinceManagerHandler),   #省份模板展示
   (r "/province.html$" , Region.ProvinceHandler),  #省份的增删改查
   (r "/CityManager.html$" , Region.CityManagerHandler),  #市模板展示
   (r "/City.html$" , Region.CityHandler),   #市的增删改查
   (r "/CountyManager.html$" , Region.CountyManagerHandler),  #县的模板展示
   (r "/County.html$" , Region.CountyHandler), #县的增删改查

四、后台模板展示Handler

#以省份为例进行介绍(市县类似):

数据获取Handler:

1
2
3
4
5
class  ProvinceManagerHandler(AdminRequestHandler):
 
     def  get( self * args,  * * kwargs):
         # 打开页面,显示所有的省
         self .render( 'Region/ProvinceManager.html' )

 本Handler主要用于从模板展示,默认如果只有这一个handler,用户看到的将是空页面。关于数据的增删改查,详见下文。

五、核心增删改查操作

再介绍增删改查之前,我们先介绍母板文件layout的前端html和继承该模板的ProvinceManager.html部分JavaScript代码:

母版layout html:

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
<! DOCTYPE  html>
< html >
< head  lang="en">
     < meta  charset="UTF-8">
     < title ></ title >
     < link  rel="stylesheet" type="text/css" href="/Statics/Admin/Plugins/jquery-easyui/themes/default/easyui.css">  #导入easyui的css
     < link  rel="stylesheet" type="text/css" href="/Statics/Admin/Plugins/jquery-easyui/themes/icon.css">  #导入easyui的图标
     < link  rel="stylesheet" type="text/css" href="/Statics/Admin/Css/Common.css"> #自定义css
 
     < script  type="text/javascript" src="/Statics/Admin/Plugins/jquery-easyui/jquery.min.js"></ script >   #导入jQuery
     < script  type="text/javascript" src="/Statics/Admin/Plugins/jquery-easyui/jquery.easyui.min.js"></ script >  #导入easyui的js
 
</ head >
< body  class="easyui-layout">
 
     < div  data-options="region:'north'" style="height:50px">
 
     </ div >
     < div  data-options="region:'south',split:true" style="height:30px;"></ div >
     < div  data-options="region:'west',split:true" title="后台管理" style="width:200px;">
         < div  id="aa" class="easyui-accordion" data-options="fit:true,border:false">
             < div  title="地区管理">  #easyui订制的左侧菜单
                 < a  id="jd_menu_province" class="jd-menu" href="/ProvinceManager.html">省</ a >
                 < a  id="jd_menu_city" class="jd-menu" href="/CityManager.html">市</ a >
                 < a  id="jd_menu_county" class="jd-menu" href="/CountyManager.html">县(区)</ a >
             </ div >
             < div  title="用户管理">
                 < a  id="user" class="jd-menu" href="#">用户管理</ a >
                 < a  id="jd_menu_merchant" class="jd-menu" href="/MerchantManager.html">商户管理</ a >
             </ div >
             < div  title="JD自营">
                 < a  id="jd_menu_product" class="jd-menu" href="/ProductManager.html">产品管理</ a >
             </ div >
         </ div >
     </ div >
     < div  data-options="region:'center'" title="{% block crumbs %} {% end %}">  #内容显示区
         {% block content %} {% end %}
     </ div >
 
</ body >
</ html >

  省份内容展示区html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
< div >
     < table  id="dg"></ table >   #easyui订制table
 
     < div  id="dlg" class="easyui-dialog" style="width:400px;height:200px;padding:10px 20px" closed="true" buttons="#dlg-buttons"> #easyui订制模态对话框,默认关闭状态
         < form  id="fm1">
             < div  class="input-group clearfix">
                 < div  class="group-label" style="width: 80px;">
                     < span >省份:</ span >
                 </ div >
                 < div  class="group-input" style="width: 300px;">
                     < input  id="dlg_nid" style="width: 200px;display: none"  name="nid"/>
                     < input  id="dlg_province" style="width: 200px" class="easyui-textbox" type="text" name="caption" data-options="required:true,missingMessage:'省份不能为空'" />  #easyui订制form验证+错误信息提示
                 </ div >
             </ div >
         </ form >
     </ div >
     < div  id="dlg-buttons">  #easyui订制按钮
         < span  id="dlg_summary" style="color: red"></ span >
         < a  href="#" class="easyui-linkbutton" iconCls="icon-ok" onclick="Save()">保存</ a >
         < a  href="#" class="easyui-linkbutton" iconCls="icon-cancel" onclick="javascript:$('#dlg').dialog('close')">取消</ a >
     </ div >
</ div >

  JavaScript代码:

1
2
3
4
5
6
7
$( function  () {
           // 加载表格数据
           InitTable();   #初始化表格内容(即查询)
           InitPagination();   #初始化分页
           InitMenu();  #初始化左侧菜单
 
       });

  首先介绍两个简单的js:

1
2
3
4
5
6
7
/*
         初始化左侧菜单
         */
         function  InitMenu(){
             $( '#aa' ).accordion( 'select' ,0);  #easyui语法:选择左侧第0个标签
             $( '#jd_menu_province' ).addClass( 'active' ); #让省份默认选中
         }
1
2
3
4
5
6
7
8
9
10
11
12
/*
       初始化分页
        */
       function  InitPagination(){
           var  pager = $( '#dg' ).datagrid( 'getPager' );
           $(pager).pagination({
               beforePageText:  '第' ,
               afterPageText:  '页 共{pages}页' ,
               displayMsg:  '当前显示{from}-{to}条记录 共{total}条数据'
 
           })
       }

关键的表格数据初始化js(查询js):

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
function  InitTable(){
     $( '#dg' ).datagrid({
         title:  '省份列表' ,
         iconCls:  'icon-save' ,    #省份图标
         url:  '/province.html' ,   #获取数据的url
         method:  'get' ,    #获取方式
         //fitColumns: true,
         idField:  'nid' , 
         singleSelect:  true ,  #默认单选
         rownumbers:  true ,  #显示行号
         striped:  true ,  #奇数行与偶数行颜色有区别
         columns:[[     #每一列标题(easyui默认根据field将后端传来的数据按表格进行显示)
             {
                 field: 'ck' ,
                 checkbox: true   #显示checkbox
             },
             {
                 field: 'nid' ,   #从数据库获取的nid
                 title: 'ID' ,  #显示名称为ID
                 width:80,  #宽度80px
                 align: 'center'   #居中显示
             },
             {
                 field: 'caption' ,
                 title: '标题' ,
                 width:180,
                 align: 'center' }
         ]],
         toolbar: [   #显示的按钮
             {
                 text:  '添加' ,   #按钮名称
                 iconCls:  'icon-add' ,   #按钮图标
                 handler: AddRow   #点击按钮后执行的返回函数
             },{
                 text: '删除' ,
                 iconCls: 'icon-remove' ,
                 handler: RemoveRow
             },{
                 text: '修改' ,
                 iconCls: 'icon-edit' ,
                 handler: EditRow
             }
         ],
         pagePosition:  'both' ,   #上下均显示分页
         pagination: true ,  #显示分页
         pageSize:10,  #默认每页显示的数据总数
         pageNumber: 1,   #默认第一页
         pageList: [10,20,50],  #分页可选每页显示数量
         loadFilter:  function (data){  #过滤函数
             return  data;
 
             }
         });
}

  上述js代码即查询时的js代码,接下来我们先看查询的后端业务处理类:

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
def  get( self * args,  * * kwargs):
      """
      获取
      :param args:
      :param kwargs:
      :return:
      """
      if  self .get_argument( 'type' None = =  'all' #如果是获取所有数据
          ret  =  { 'status' True 'rows' : "", 'summary' :''}   #将来要返回给前端的字典,包含是否获取成功的状态、获取的数据、错误信息
          try :
              region_service  =  RegionService(RegionRepository())   #将数据库处理类的对象传入数据库业务协调类
              all_province_list  =  region_service.get_province()  #获取所有省份
              ret[ 'rows' =  all_province_list  #将省份数据添加进返回前端的字典
          except  Exception as e:
              ret[ 'status' =  False
              ret[ 'summary' =  str (e)
          self .write(json.dumps(ret))  #返回给前端
      else :   #如果是获取分页数据
          ret  =  { 'status' True , 'total' 0 'rows' : [],  'summary' : ''}
          try :
              rows  =  int ( self .get_argument( 'rows' 10 )) #每页显示10条
              page  =  int ( self .get_argument( 'page' 1 ))  #显示第一页
              start  =  (page - 1 ) * rows 开始条数
 
              region_service  =  RegionService(RegionRepository())
              row_list  =  region_service.get_province_by_page(start, rows)  #根据分页获取省份数据
              row_count  =  region_service.get_province_count()   #获取省份总数
 
              ret[ 'total' =  row_count
              ret[ 'rows' =  row_list
          except  Exception as e:
              ret[ 'status' =  False
              ret[ 'summary' =  str (e)
 
          self .write(json.dumps(ret))   #返回给前端

数据库业务协调处理类的对应操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class  RegionService:
     def  __init__( self , region_repository):
         self .regionRepository  =  region_repository
 
     def  get_province_count( self ):
         count  =  self .regionRepository.fetch_province_count()  #获取省份总数
         return  count
 
     def  get_province_by_page( self , start, offset):  #根据分页获取省份
 
         result  =  self .regionRepository.fetch_province_by_page(start, offset)
         return  result
 
     def  get_province( self ):  #获取所有省份
         return  self .regionRepository.fetch_province()

 数据库操作类相关操作:

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
class  RegionRepository(IRegionRepository):
 
     def  __init__( self ):
         self .db_conn  =  DbConnection()  #实例化数据库链接对象(只需创建一次对象,下面所有方法都不需要再创建)
 
     def  fetch_province( self ):  #获取所有省份
         cursor  =  self .db_conn.connect()
         sql  =  """select nid,caption from province order by nid desc """
         cursor.execute(sql)
         db_result  =  cursor.fetchall()
         self .db_conn.close()
         return  db_result
 
 
     def  fetch_province_by_page( self , start, offset):  #根据分页获取省份
         ret  =  None
         cursor  =  self .db_conn.connect()
         sql  =  """select nid,caption from province order by nid desc limit %s offset %s """
         cursor.execute(sql, (offset, start))
         db_result  =  cursor.fetchall()
         self .db_conn.close()
         return  db_result
     def  fetch_province_count( self ):  #获取省份总数
         cursor  =  self .db_conn.connect()
         sql  =  """select count(1) as count from province """
         cursor.execute(sql)
         db_result  =  cursor.fetchone()
         self .db_conn.close()
         return  db_result[ 'count' ]

  以上就是查询操作的所有过程。

增加:

js:

1
2
3
4
5
6
7
8
9
10
/*
         添加
         */
         function  AddRow(){
             // 显示对话框,由于希望添加则将方法设置为POST
             $( '#fm1' ).form( 'clear' ); #清空上次form的内容
             $( '#dlg' ).dialog( 'open' ).dialog( 'setTitle' , '创建省份' ); #设置模态对话框标签是创建省份
             $( '#dlg_summary' ).empty(); #清空错误信息
             METHOD =  'post' ;   #设置提交方式为post
         }

  增加操作实际上就做了一个操作:打开模态对话框。

前端页面展示:

 

当用户输入需要添加的省份,接下来点击保存按钮,数据将被写入数据库并在前端显示:

保存的js代码:

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
/*
     保存按钮
      */
     function  Save(){
         var  isValid = $( '#fm1' ).form( 'validate' );前端form验证
         if (isValid){
             $.ajax({
                 url:  '/province.html' ,  #提交的url
                 type: METHOD,   #根据之前定义的方法进行提交
                 data: {caption: $( '#dlg_province' ).val(),nid:  $( '#dlg_nid' ).val()}, #提交的数据
                 dataType:  'json' ,  #数据格式
                 success:  function (data){  #如果后端成功返回数据
                     if (data.status){  #后端操作成功
                         $( '#fm1' ).form( 'clear' ); #清空form内容
                         $( '#dlg' ).dialog( 'close' ); #关闭模态对话框
                         $( '#dg' ).datagrid( 'reload' ); #重新加载数据
                     } else {
                         $( '#dlg_summary' ).text(data.summary); #否则显示错误信息
                     }
                 }
             })
         } else {
             // 前端验证通过
         }
         // $('#fm').form('clear');
     }

  增加对应的后端业务处理方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def  post( self * args,  * * kwargs):
        """
        添加
        :param args:
        :param kwargs:
        :return:
        """
        ret  =  { 'status' False 'summary' : ''}
        caption  =  self .get_argument( 'caption' None )
        if  not  caption:
            ret[ 'summary' =  '省份不能为空'
        else :
            try :
 
                region_service  =  RegionService(RegionRepository())
                result  =  region_service.create_province(caption)  #创建省份,如果省份已存在,返回None
                if  not  result:
                    ret[ 'summary' =  '省份已经存在'
                else :
                    ret[ 'status' =  True  #操作成功
            except  Exception as e:
                ret[ 'summary' =  str (e)
 
        self .write(json.dumps(ret))  #返回给前端

 数据库协调处理类对应的方法:

1
2
3
4
5
def  create_province( self , caption):
     exist  =  self .regionRepository.exist_province(caption) #先判断省份是否存在,如果存在,该方法返回值为None
     if  not  exist:
          self .regionRepository.add_province(caption)  #创建省份
          return  True

 数据库对应操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def  exist_province( self , caption):  #省份是否存在
      cursor  =  self .db_conn.connect()
      sql  =  """select count(1) as count from province where caption=%s """
      cursor.execute(sql, (caption,))
      db_result  =  cursor.fetchone()
      self .db_conn.close()
 
      return  db_result[ 'count' ]
 
  def  add_province( self , caption):   #创建省份
      cursor  =  self .db_conn.connect()
      sql  =  """insert into province (caption) values(%s)"""
      effect_rows  =  cursor.execute(sql, (caption,))
      self .db_conn.close()
      return  effect_rows

  以上就是省份添加的全部过程。

修改:

实际上修改和添加基本上是一样的,接下来只介绍与添加不同的地方:

js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
       修改
       */
       function  EditRow(){
           // 显示对话框,由于希望修改则将方法设置为PUT
 
           // 获取选中的值,将其赋值到页面上,然后ajax提交
           var  row = $( '#dg' ).datagrid( 'getSelected' );
           $( '#dlg_summary' ).empty();
           if (row){
               METHOD =  'put' ;
               $( '#fm1' ).form( 'clear' );
               $( '#fm1' ).form( 'load' ,row);
               $( '#dlg' ).dialog( 'open' ).dialog( 'setTitle' , '修改省份' );
 
           } else {
               $.messager.alert( '警告' '请选择要修改的行' 'warning' );
           }
 
       }

  这里弹出模态对话框,与添加不同的是,修改需要将用户原有数据存放在input标签中,方便用户进行修改。同时,将提交方法修改为put。

修改模态对话框示例截图:

接下来用户修改完成后的点击保存,关于保存的js代码详见上文添加部分。

保存的后台业务处理handler方法:

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
def  put( self * args,  * * kwargs):
        """
        更新
        :param args:
        :param kwargs:
        :return:
        """
        ret  =  { 'status' False 'summary' : ''}
        nid  =  self .get_argument( 'nid' None )
        caption  =  self .get_argument( 'caption' None )
        if  not  caption  or  not  nid:
            ret[ 'summary' =  '省份不能为空'
        else :
            try :
 
                region_service  =  RegionService(RegionRepository())
                result  =  region_service.modify_province(nid, caption)
 
                if  not  result:
                    ret[ 'summary' =  '省份已经存在'
                else :
                    ret[ 'status' =  True
            except  Exception as e:
                ret[ 'summary' =  str (e)
        self .write(json.dumps(ret))

  该方法与添加时的方法基本一致,这里不做过多介绍。

数据库协调处理类对应的方法:

1
2
3
4
5
def  modify_province( self , nid, caption):
        exist  =  self .regionRepository.exist_province(caption)
        if  not  exist:
             self .regionRepository.update_province(nid, caption)  #更新省份
             return  True

数据库操作对应类的方法:

1
2
3
4
5
6
def  update_province( self , nid, caption): #更新省份
       cursor  =  self .db_conn.connect()
       sql  =  """update province set caption=%s where nid=%s """
       effect_rows  =  cursor.execute(sql, (caption, nid,))
       self .db_conn.close()
       return  effect_rows

  以上就是省份数据修改的全部过程。

删除:

js:

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
60
61
62
63
64
65
66
67
68
69
/*
        删除
        */
        function  RemoveRow(){
            // 获取已经选中的行
            var  rows = $( '#dg' ).datagrid( 'getSelections' );
            console.log(rows);
            if (rows.length<=0){
                // 警告框
                $.messager.alert( '警告' '请选择要删除的行' 'warning' );
            } else  if (rows.length>1){
                $.messager.alert( '警告' '不支持批量删除' );
            } else {
                // 确认框
                $.messager.confirm( '确定' '您确定要删除吗?' function  (status) {  #easyui订制的确认框
                    if (status){
                        // 点击确定
                        // 获取当前选中行的值,Ajax发送到后台
                        var  row = rows[0];
                        $.ajax({
                            url:  'province.html' ,
                            type:  'delete' ,
                            data: {nid: row.nid},
                            dataType:  'json' ,
                            success:  function  (data) {
                                if (data.status){
                                    //删除成功
                                    $.messager.show({   #easyui订制的messager框
                                        msg: '删除成功' ,
                                        showType: 'slide' ,  #淡出
                                        showSpeed: 500,  #速度
                                        timeout: 5,   #显示5秒
                                        style:{
                                            right: '' ,
                                            top:document.body.scrollTop+document.documentElement.scrollTop,  #在屏幕上方显示
                                            bottom: ''
                                        }
                                    });
                                    // 重新加载表格
                                    var  rowIndex = $( '#dg' ).datagrid( 'getRowIndex' , row);
                                    $( '#dg' ).datagrid( 'deleteRow' ,rowIndex);
                                    $( '#dg' ).datagrid( 'reload' );
 
                                    // 删除指定行
                                    //var rowIndex = dt.datagrid('getRowIndex', row);
                                    //dt.datagrid('deleteRow',rowIndex);
 
                                } else {
                                    //删除失败
                                    // $.messager.alert('错误信息', data.summary ,'error');
                                    $.messager.show({   #显示错误信息
                                        icon:  'error' ,
                                        title: '错误信息' ,
                                        msg:data.summary,
                                        showType: 'slide' ,
                                        timeout: 0,
                                        style:{
                                            right: '' ,
                                            top:document.body.scrollTop+document.documentElement.scrollTop,
                                            bottom: ''
                                        }
                                    });
                                }
                            }
                        });
                    }
                })
            }
        }

  后台handler类对应方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def  delete( self * args,  * * kwargs):
        """
        删除
        :param args:
        :param kwargs:
        :return:
        """
        ret  =  { 'status' False 'summary' : ''}
 
        nid  =  self .get_argument( 'nid' None )
 
        if  not  nid:
            ret[ 'summary' =  '请选择要删除的省份'
        else :
            # 调用service去删除吧...
            # 如果删除失败,则显示错误信息
            try :
                region_service  =  RegionService(RegionRepository())
                region_service.delete_province(nid)  #根据nid删除省份
                ret[ 'status' =  True
            except  Exception as e:
                ret[ 'summary' =  str (e)
        self .write(json.dumps(ret))

  数据库业务协调处理类对应的方法:

1
2
3
def  delete_province( self , nid):
 
        self .regionRepository.remove_province(nid)

  数据库操作类对应方法:

1
2
3
4
5
6
def  remove_province( self , nid):
        cursor  =  self .db_conn.connect()
        sql  =  """delete from province where nid=%s """
        effect_rows  =  cursor.execute(sql, (nid,))
        self .db_conn.close()
        return  effect_rows

  以上就是删除的全部过程。

总结:本文主要以省份的增删改查为例介绍了前端easyui的使用,后端handler、数据库业务协调处理类、数据库操作类的整个流程。下节我们将介绍市县管理中与省份不同的部分,欢迎下次收看!如果本文对您有参考价值,欢迎帮博主点下文章下方的推荐,谢谢!

Python-管理后台脚手架实现了RBAC(基于角色的访问控制)和一个简单的SQLAlchemy的映射工具基于Tornado。管理后台脚手架是一个基础的框架,用于快速搭建管理后台系统。下面我详细介绍一下这两个功能的实现。 首先,RBAC是一种常见的权限管理模型,它通过对用户、角色和权限进行关联,实现了灵活的访问控制。在管理后台脚手架中,RBAC的实现包括以下步骤: 1. 定义角色和权限:可以通过配置文件或者数据库定义角色和权限列表,例如:管理员、编辑、查看等。 2. 分配角色和权限:根据具体需求,将用户分配给相应的角色,同时为角色分配适当的权限。 3. 鉴权:在用户登录后,可以根据用户的角色和权限,通过一些逻辑判断来决定用户是否具有执行某个操作的权限。 其次,SQLAlchemy是Python中一个强大的ORM(对象关系映射)工具,它可以将数据库表映射为Python类,方便开发者使用面向对象的方式进行数据库操作。在管理后台脚手架中,SQLAlchemy的mapper工具用于简化数据库操作的代码,提高开发效率。具体实现包括以下步骤: 1. 定义模型类:通过定义Python类,使用SQLAlchemy提供的装饰器和字段类型,将数据库表映射为Python类,定义了表结构和字段类型等信息。 2. 创建数据库连接:通过SQLAlchemy提供的连接池机制,设置数据库连接参数,并创建数据库会话。 3. 数据库操作:通过调用模型类的方法,进行数据库的增删改查操作。SQLAlchemy的mapper工具将会自动创建SQL语句并执行。开发者无需手动编写SQL语句。 总之,使用Python-管理后台脚手架可以快速搭建一个具有RBAC权限管理和使用SQLAlchemy的mapper工具的管理后台系统。这些功能的实现大大简化了开发者的工作,提高了开发效率和系统的可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值