phpBB3导入版面的Python脚本
关联的数据表
在phpBB3中导入版面时, 需要处理的有两张表, 一个是 forums, 一个是 acl_groups.
如果是干净的论坛, 可以不保留安装时填入的默认分区和版面, 直接用以下语句初始化:
-- 清空 forums 表
TRUNCATE phpbb_forums;
-- 清空 acl_groups 表
TRUNCATE phpbb3015.phpbb_acl_groups;
-- 填入初始化权限
INSERT INTO `phpbb_acl_groups` VALUES (1,0,85,0,1),(1,0,93,0,1),(1,0,111,0,1),(5,0,0,5,0),(5,0,0,1,0),(2,0,0,6,0),(3,0,0,6,0),(4,0,0,5,0),(4,0,0,10,0),(7,0,0,23,0);
如果是已经存在版面, 并且需要保留版面的论坛, 则仅需要记下当前的最大right_id
SELECT MAX(right_id) FROM phpbb_forums
.
需要的最小数据集
需要的最小字段为 `forum_id`, `parent_id`, `left_id`, `right_id`, `forum_name`, `forum_type`
构造版面数据
phpBB3的版面为单个父节点的树状结构, 使用了parent_id, left_id, right_id 来标识版面间的层级关系以及排序顺序. 在构造版面数据时, 需要的就是采集最小数据集, 并正确生成parent_id, left_id和right_id. 下面的例子使用的版面, 原数据是分区 + 版面的结构, 分区有层级关系, 版面有层级关系, 分区的ID与版面的ID有重叠, 并且分区与版面之间存在多个父节点的情况. 需要在生成中进行调整.
创建一个可用的ID序列, 用于将分区ID映射到可用ID序列上
数量不大的话, 这一步可以通过手工完成, 根据分区的数量, 观察版面的ID序列, 列出可用的ID做成list
availableIds = [3, 8, 11, 12, 13, 27, 30, ...]
将分区加入版面列表
遍历分区, 将旧ID映射到新ID上, 需要两次遍历, 第二次遍历时构造父子关系, children变量用于在最后生成left_id和right_id
boardsDict = {} # The mapping between Id => board
# Build the section map
allSections = rbcommon.tb_section.find({}).sort('rank', 1)
boards = [] # Record all boards
topBoards = [] # the root board Ids
sectionMap = {} # The mapping between old section Id => new board Id, for assigning new Ids for the sections
cusor = 0
for section in allSections:
sectionMap[str(section['_id'])] = availableIds[cusor]
newId = availableIds[cusor]
board = {
'oid': section['_id'], 'oldPid': section['parentId'],
'_id': newId, 'name2': section['name2'], 'is_folder': 'true',
'desc': section['desc'],
'children': []
}
boards.append(board)
boardsDict[board['_id']] = board
cusor += 1
for board in boards:
if (board['oldPid'] != 0):
board['parentId'] = sectionMap[str(board['oldPid'])]
parent = boardsDict[board['parentId']]
parent['children'].append(board['_id'])
else:
board['parentId'] = 0
topBoards.append(board['_id'])
for board in boards:
print('oid:{}, oldPid:{}, _id:{}, parentId:{}, children:{}'.format(board['oid'], board['oldPid'], board['_id'], board['parentId'], board['children']))
将版面加入列表
# Build the boards
mongoBoards = rbcommon.tb_board.find({})
for mongoBoard in mongoBoards:
board = {
'oid': mongoBoard['_id'], 'oldPid': 0, 'parentId': 0,
'_id': mongoBoard['_id'], 'name2': mongoBoard['name2'], 'is_folder': mongoBoard['is_folder'],
'desc': mongoBoard['name'],
'children': []
}
boards.append(board)
if (board['_id'] in boardsDict.keys()):
print('Error: {}'.format(board['_id']))
exit
boardsDict[board['_id']] = board
完善版面层级关系
# Build the boards tree
allSectionToBoards = rbcommon.tb_section_to_board.find({})
for s2b in allSectionToBoards:
if (s2b['parentId'] == 0):
# parent is section
parentId = sectionMap[str(s2b['sectionId'])]
parent = boardsDict[parentId]
board = boardsDict[s2b['boardId']]
# avoid the multiple parent
if (board['parentId'] > 0):
print('Duplicate {} for {}, board:{}'.format(parentId, board['parentId'], s2b['boardId']))
continue
board['parentId'] = parentId
parent['children'].append(s2b['boardId'])
else:
# parent is board
parent = boardsDict[s2b['parentId']]
board = boardsDict[s2b['boardId']]
# avoid the multiple parent
if (board['parentId'] > 0):
print('Duplicate {} for {}, board:{}'.format(s2b['parentId'], board['parentId'], s2b['boardId']))
continue
board['parentId'] = s2b['parentId']
parent['children'].append(s2b['boardId']) print("All boards:")
for board in boards:
print('oid:{}, oldPid:{}, _id:{}, parentId:{}, folder:{}, children:{}'.format(
board['oid'], board['oldPid'], board['_id'], board['parentId'], board['is_folder'], board['children']))
使用递归填充left_id和right_id
其中counter的取值, 如果是干净的论坛并且前面已经执行了truncate, 就将counter设成1, 否则设成前面得到的right_id最大值 + 1. 这样新导入的分区和版面都会出现在原有分区和版面的下方
# Build the leftId and rightId
markLeftAndRight(topBoards)
print("Marked boards:")
for board in boards:
print('_id:{}, parentId:{}, left:{}, right:{}, folder:{}, children:{}'.format(
board['_id'], board['parentId'], board['leftId'], board['rightId'], board['is_folder'], board['children'])) # 用于递归的方法
def markLeftAndRight(idList):
global counter
for id in idList:
board = boardsDict[id]
if ('leftId' in board):
print('Error: {}'.format(id))
exit
board['leftId'] = counter
counter += 1
if (len(board['children']) > 0):
markLeftAndRight(board['children'])
board['rightId'] = counter
counter += 1
.
写入MySQL
用pymsql写入mysql, 每写入一个版面, 同时写入对应的权限, 注意分区和版面的默认权限数据是不一样的.
# Write it to MySQL
for board in boards:
try:
with rbcommon.mysqlclient.cursor() as cursor:
# insert forum
sql = '''INSERT INTO `phpbb_forums` (`forum_id`, `parent_id`, `left_id`, `right_id`, `forum_parents`, `forum_name`, `forum_desc`,
`forum_rules`, `forum_type`)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)'''
cursor.execute(sql, (
board['_id'],
board['parentId'],
board['leftId'],
board['rightId'],
'',
board['name2'],
board['desc'],
'',
0 if (board['is_folder'] == 'true') else 1))
rbcommon.mysqlclient.commit()
# insert acl_group
if (board['is_folder'] == 'true'):
sql = 'INSERT INTO `phpbb_acl_groups` VALUES (1,%s,0,17,0),(2,%s,0,17,0),(3,%s,0,17,0),(6,%s,0,17,0)'
cursor.execute(sql, (
board['_id'], board['_id'], board['_id'], board['_id']))
rbcommon.mysqlclient.commit()
else:
sql = 'INSERT INTO `phpbb_acl_groups` VALUES (1,%s,0,17,0),(2,%s,0,15,0),(3,%s,0,15,0),(4,%s,0,21,0),(5,%s,0,14,0),(5,%s,0,10,0),(6,%s,0,19,0),(7,%s,0,24,0)'
cursor.execute(sql, (
board['_id'], board['_id'], board['_id'], board['_id'], board['_id'], board['_id'], board['_id'], board['_id']))
rbcommon.mysqlclient.commit() except Exception as e:
print(e)
数据导入后, 使用管理员帐号先在后台清空缓存, 再查看和编辑版面
phpBB3导入版面的Python脚本的更多相关文章
- phpBB3导入用户的Python脚本
关联的数据表 在phpBB3中导入用户时, 需要处理的有两张表, 一个是 users, 一个是 user_group. 如果是新安装的论坛, 在每次导入之前, 用以下语句初始化: DELETE FRO ...
- phpBB3导入帖子的Python脚本
关联的数据表 在phpBB3中导入用户时, 需要处理的有两张表, 一个是 topics, 一个是 posts.为了方便与原数据关联, 需要在这两个表上新增一个字段并建立唯一索引 ALTER TABLE ...
- C#调用python脚本
因项目需要,需要使用C#控制台程序执行python脚本,查询各种资料后可以成功调用了,记录一下,以备后面遗忘. 只尝试了两种调用方式,第一种只适用于python脚本中不包含第三方模块的情况,第二种针对 ...
- Python实用案例,Python脚本,Python实现每日更换“必应图片”为“桌面壁纸”
往期回顾 Python实现自动监测Github项目并打开网页 Python实现文件自动归类 Python实现帮你选择双色球号码 前言: 今天我们就利用python脚本实现每日更换"必应图片& ...
- Python脚本控制的WebDriver 常用操作 <六> 打印当前页面的title及url
下面将使用WebDriver来答应浏览器页面的title和访问的地址信息 测试用例场景 测试中,访问1个页面然后判断其title是否符合预期是很常见的1个用例: 假设1个页面的title应该是'hel ...
- python 脚本查看微信把你删除的好友--win系统版
PS:目测由于微信改动,该脚本目前不起作用 下面截图来自原作者0x5e 相信大家在微信上一定被上面的这段话刷过屏,群发消息应该算是微信上流传最广的找到删除好友的方法了.但群发消息不仅仅会把通讯录里面所 ...
- *** Python版一键安装脚本
本脚本适用环境:系统支持:CentOS 6,7,Debian,Ubuntu内存要求:≥128M日期:2018 年 02 月 07 日 关于本脚本:一键安装 Python 版 *** 的最新版.友情提示 ...
- zabbix3.4用Python脚本Excel批量导入主机
1.安装xlrd读取Excel文件 1.1. 下载setuptools-38.2.4.zip,上传至zabbix服务器解压安装,下载地址:https://pypi.python.org/package ...
- 自己来编写一份 Python 脚本 第一版
解决问题 我们已经探索了 Python 语言中的许多部分,现在我们将通过设计并编写一款程序来了解如何把这些部分组合到一起.这些程序一定是能做到一些有用的事情.这节的Python教程就是教大家方法去学习 ...
随机推荐
- mybatis中union可以用if判断连接,但是<select>中第一个select语句不能被if判断,因此可以从dual表中查询null来凑齐。union如果使用order by排序,那么只能放在最后一个查询语句的位置,并且不能带表名。
<!-- 一址多证纳税人分析表 --> <select id="yzdznsrlistPage" parameterType="page" r ...
- BZOJ 4260 Codechef REBXOR (区间异或和最值) (01字典树+DP)
<题目链接> 题目大意:给定一个序列,现在求出两段不相交的区间异或和的最大值. 解题分析: 区间异或问题首先想到01字典树.利用前缀.后缀建树,并且利用异或的性质,相同的两个数异或变成0, ...
- 从零搭建 ES 搜索服务(五)搜索结果高亮
一.前言 在实际使用中搜索结果中的关键词前端通常会以特殊形式展示,比如标记为红色使人一目了然.我们可以通过 ES 提供的高亮功能实现此效果. 二.代码实现 前文查询是通过一个继承 Elasticsea ...
- MongoDB+php7搭建
0x00前言: 今天一位非计算机专业的朋友问我怎么打开.bson文件,我第一反应.bson文件是什么,网上查了下是mongodb的传输文件.也就是类似于mysql的.sql文件一样 之前看过mongo ...
- Python itertools模块详解
这货很强大, 必须掌握 文档 链接 http://docs.python.org/2/library/itertools.html pymotw 链接 http://pymotw.com/2/iter ...
- C#循环语句整理
for.while.do while和switch暂时没发现与c++的不同,这里只整理foreach. foreach foreach的作用是遍历集合中的所有元素.foreach语句中的表达式由关键字 ...
- OSPF补全计划-2
想起来几个面试题: 1. OSPF在什么情况下会stuck in Exstart /Exchange状态? 我知道的一个答案是两个端口的mtu不一致.当然整个也不是绝对,因为可以用ip ospf mt ...
- BZOJ.4818.[SDOI2017]序列计数(DP 快速幂)
BZOJ 洛谷 竟然水过了一道SDOI!(虽然就是很水...) 首先暴力DP,\(f[i][j][0/1]\)表示当前是第\(i\)个数,所有数的和模\(P\)为\(j\),有没有出现过质数的方案数. ...
- Java并发编程(十)-- Java中的锁
在学习或者使用Java的过程中进程会遇到各种各样的锁的概念:公平锁.非公平锁.自旋锁.可重入锁.偏向锁.轻量级锁.重量级锁.读写锁.互斥锁.死锁.活锁等,本文将简概的介绍一下各种锁. 公平锁和非公平锁 ...
- Redis设计与实现:读书笔记之二
1.数据库 Redis服务器一般包含多个db,默认16个. 切换数据库 每个redis客户端都有自己的目标数据库,默认为0,可以通过select 1,切换数据库. 设置键的生存周期和过期时间 PTTL ...