有没有用 Python 写的论坛程序,支持从 Discuz 迁移数据?
目前比较感兴趣的是 Vanilla ,但不知道怎么迁移数据。。
有没有用 Python 写的论坛程序,支持从 Discuz 迁移数据?
13 回复
自己看下表结构直接转过去,跑几句 sql 的事。
有,FlaskBB 是一个不错的选择。它用 Python 的 Flask 框架开发,功能完整,社区活跃。虽然官方没有内置的 Discuz 迁移工具,但它的数据库结构清晰,我们可以写一个 Python 脚本来完成数据迁移。
核心思路是:连接 Discuz 的 MySQL 数据库,读取用户、版块、帖子等数据,然后按照 FlaskBB 的模型结构,通过 SQLAlchemy 写入到新数据库。
下面是一个概念性的迁移脚本框架,展示了主要的数据表转换逻辑。你需要根据实际的 Discuz 版本和表前缀修改数据库连接信息和字段映射。
import pymysql
from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime, ForeignKey, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import hashlib
import pytz
# 1. 数据库连接配置 (根据你的实际情况修改)
DZ_DB_CONFIG = {
'host': 'localhost',
'user': 'your_dz_user',
'password': 'your_dz_password',
'database': 'discuz_db',
'charset': 'utf8mb4',
'port': 3306,
'table_prefix': 'pre_' # Discuz 表前缀
}
FLASKBB_DB_URI = 'sqlite:///flaskbb.db' # 或 'mysql+pymysql://...'
# 2. 连接数据库
dz_conn = pymysql.connect(**DZ_DB_CONFIG)
dz_cursor = dz_conn.cursor(pymysql.cursors.DictCursor)
# FlaskBB ORM 模型基类
Base = declarative_base()
# 3. 定义关键的 FlaskBB 模型 (这里只列核心字段)
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(200), unique=True)
email = Column(String(200), unique=True)
password = Column(String(200))
date_joined = Column(DateTime, default=datetime.utcnow)
# ... 其他字段
class Category(Base):
__tablename__ = 'categories'
id = Column(Integer, primary_key=True)
title = Column(String(255))
description = Column(Text)
class Forum(Base):
__tablename__ = 'forums'
id = Column(Integer, primary_key=True)
category_id = Column(Integer, ForeignKey('categories.id'))
title = Column(String(255))
description = Column(Text)
class Topic(Base):
__tablename__ = 'topics'
id = Column(Integer, primary_key=True)
forum_id = Column(Integer, ForeignKey('forums.id'))
user_id = Column(Integer, ForeignKey('users.id'))
title = Column(String(255))
date_created = Column(DateTime, default=datetime.utcnow)
# ... 其他字段
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
topic_id = Column(Integer, ForeignKey('topics.id'))
user_id = Column(Integer, ForeignKey('users.id'))
content = Column(Text)
date_created = Column(DateTime, default=datetime.utcnow)
# 4. 创建 FlaskBB 数据库表
engine = create_engine(FLASKBB_DB_URI)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# 5. 数据迁移函数
def migrate_users():
"""迁移用户数据"""
table = f"{DZ_DB_CONFIG['table_prefix']}common_member"
dz_cursor.execute(f"SELECT uid, username, email, password, regdate FROM {table}")
for row in dz_cursor.fetchall():
# Discuz 密码需要特殊处理,这里假设使用默认的 md5 加密
# 实际可能需要根据 Discuz 的加密方式调整
user = User(
id=row['uid'],
username=row['username'],
email=row['email'],
password=row['password'], # 注意:可能需要重新加密或使用兼容方式
date_joined=datetime.fromtimestamp(row['regdate'], tz=pytz.UTC)
)
session.merge(user) # 使用 merge 避免 ID 冲突
session.commit()
print("用户数据迁移完成")
def migrate_forums():
"""迁移版块数据"""
# 先迁移分类
dz_cursor.execute(f"SELECT fid, name, description FROM {DZ_DB_CONFIG['table_prefix']}forum_forum WHERE type='group'")
for row in dz_cursor.fetchall():
category = Category(id=row['fid'], title=row['name'], description=row['description'])
session.merge(category)
# 再迁移论坛版块
dz_cursor.execute(f"SELECT fid, fup, name, description FROM {DZ_DB_CONFIG['table_prefix']}forum_forum WHERE type='forum'")
for row in dz_cursor.fetchall():
forum = Forum(id=row['fid'], category_id=row['fup'], title=row['name'], description=row['description'])
session.merge(forum)
session.commit()
print("版块数据迁移完成")
def migrate_topics_and_posts():
"""迁移主题和帖子"""
# 迁移主题
dz_cursor.execute(f"""
SELECT tid, fid, authorid, subject, dateline
FROM {DZ_DB_CONFIG['table_prefix']}forum_thread
WHERE displayorder>=0
""")
for row in dz_cursor.fetchall():
topic = Topic(
id=row['tid'],
forum_id=row['fid'],
user_id=row['authorid'],
title=row['subject'],
date_created=datetime.fromtimestamp(row['dateline'], tz=pytz.UTC)
)
session.merge(topic)
# 迁移帖子
dz_cursor.execute(f"""
SELECT pid, tid, authorid, message, dateline
FROM {DZ_DB_CONFIG['table_prefix']}forum_post
WHERE invisible=0 AND first=1
""")
for row in dz_cursor.fetchall():
post = Post(
id=row['pid'],
topic_id=row['tid'],
user_id=row['authorid'],
content=row['message'],
date_created=datetime.fromtimestamp(row['dateline'], tz=pytz.UTC)
)
session.merge(post)
session.commit()
print("主题和帖子迁移完成")
# 6. 执行迁移
if __name__ == '__main__':
try:
print("开始迁移数据...")
migrate_users()
migrate_forums()
migrate_topics_and_posts()
print("所有数据迁移完成!")
except Exception as e:
session.rollback()
print(f"迁移过程中出现错误: {e}")
finally:
dz_cursor.close()
dz_conn.close()
session.close()
重要提醒:
- 密码问题:Discuz 的密码加密方式可能与 FlaskBB 不兼容。脚本中直接复制了密码字段,这很可能导致用户无法登录。你需要研究两者的加密方式,并在迁移时进行转换,或者引导用户在首次登录时重置密码。
- 数据完整性:这个脚本只迁移了最核心的用户、版块、主题和帖子数据。像用户组权限、私人消息、附件、点赞等数据需要你根据业务需求额外处理。
- 测试:务必先在测试环境完整运行,验证数据正确性和完整性后,再对生产数据进行操作。
- 备份:操作前,备份好 Discuz 和 FlaskBB 的数据库。
总结建议:用 FlaskBB 加自定义迁移脚本是目前最可行的方案。
楼主你要是搞定了记得写个教程
这个不是很简单吧,需要比较熟悉 discuz
就是一个数据库换个程序读写而已吧?很难吗
我搜了一下,不是 Python 写的吧
discuz 那么多复杂的业务逻辑,只读个 sql 应该不行吧
楼上说说都简单的。真要转起来,一堆麻烦事呢。
DZ 那么多的表,没看懂估计还不好转
友情提醒楼上们: Discuz 的表有三百多个
DZ 里面巨多表逻辑很复杂,几句 sql 还真搞不定
关键是目标数据库简单。
楼主成功了也分享一下教程, mark 一下

