Deepseek has found the solution to the problem:
There are several important fields missing in your script. Based on the real structure of the Flarum tables, we need to make these corrections.
It was recoded as follows ( a history):
Deepseek ha encontrado la solución al problema:
1) Hay varios campos importantes que están faltando en el script. Basado en la estructura real de las tablas de Flarum, se necesitaba hacer estas correcciones. Se recodificó:
import pymysql
import datetime
# --------------------------------
# Conexiones a las bases de datos
# --------------------------------
conn_old = pymysql.connect(
host="localhost",
user="root",
password="-----------",
database="fictograma_old",
cursorclass=pymysql.cursors.DictCursor
)
conn_new = pymysql.connect(
host="localhost",
user="forograma_user",
password="D---------",
database="forograma_db",
cursorclass=pymysql.cursors.DictCursor
)
cur_old = conn_old.cursor()
cur_new = conn_new.cursor()
# --------------------------
# Migrar usuarios
# --------------------------
def migrate_users():
cur_old.execute("SELECT * FROM usuarios")
users = cur_old.fetchall()
user_map = {}
for u in users:
cur_new.execute("""
INSERT INTO fg_users (username, email, password, joined_at, is_email_confirmed, discussion_count, comment_count)
VALUES (%s, %s, %s, %s, 1, 0, 0)
ON DUPLICATE KEY UPDATE username = username
""", (
u["username"],
u["email"],
u["password"],
u.get("fecha_registro") or datetime.datetime.now()
))
user_map[u["id"]] = cur_new.lastrowid
conn_new.commit()
print(f"👤 Usuarios migrados: {len(users)}")
return user_map
# --------------------------
# Obtener o crear tag Literatura
# --------------------------
def get_literature_tag():
cur_new.execute("SELECT id FROM fg_tags WHERE slug='literatura'")
tag = cur_new.fetchone()
if tag:
return tag["id"]
cur_new.execute("""
INSERT INTO fg_tags (name, slug, position, discussion_count)
VALUES ('Literatura', 'literatura', 0, 0)
""")
conn_new.commit()
return cur_new.lastrowid
# --------------------------
# Migrar cuentos → discusiones y posts
# --------------------------
def migrate_cuentos(user_map, tag_id):
cur_old.execute("SELECT * FROM cuentos")
cuentos = cur_old.fetchall()
for c in cuentos:
user_id = user_map.get(c["user_id"])
if not user_id:
continue
# Crear slug
slug = c["titulo"].strip().replace(" ", "-").lower()[:255] # Limitar a 255 chars
# Obtener fecha de publicación
created_at = c.get("fecha_publicacion") or datetime.datetime.now()
# Contenido del cuento
contenido = ""
if c.get("descripcion"):
contenido += c["descripcion"].strip() + "\n\n"
if c.get("contenido"):
contenido += c["contenido"].strip()
if not contenido.strip():
contenido = "Sin contenido disponible."
# IMPORTANTE: Formato correcto para Flarum
# Flarum usa este formato específico para el contenido
contenido_formatted = f'<!--t|0-->{contenido}<!--t-->'
# PRIMERO: Insertar el POST (contenido)
cur_new.execute("""
INSERT INTO fg_posts
(discussion_id, number, created_at, user_id, type, content, is_private, is_approved)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""", (
None, # discussion_id temporalmente NULL
1, # number = 1 (primer post)
created_at,
user_id,
'comment', # type = 'comment'
contenido_formatted,
0, # is_private
1 # is_approved
))
first_post_id = cur_new.lastrowid
# AHORA: Insertar la DISCUSIÓN con referencia al post
cur_new.execute("""
INSERT INTO fg_discussions
(title, slug, user_id, created_at, comment_count, participant_count,
first_post_id, last_post_id, last_posted_at, last_posted_user_id, last_post_number,
is_private, is_approved, post_number_index)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""", (
c["titulo"][:200], # Limitar a 200 chars
slug,
user_id,
created_at,
1, # comment_count
1, # participant_count
first_post_id, # first_post_id
first_post_id, # last_post_id
created_at, # last_posted_at
user_id, # last_posted_user_id
1, # last_post_number
0, # is_private
1, # is_approved
1 # post_number_index
))
discussion_id = cur_new.lastrowid
# ACTUALIZAR el post con el discussion_id correcto
cur_new.execute("""
UPDATE fg_posts
SET discussion_id = %s
WHERE id = %s
""", (discussion_id, first_post_id))
# Asignar tag "Literatura"
cur_new.execute("""
INSERT INTO fg_discussion_tag (discussion_id, tag_id)
VALUES (%s, %s)
""", (discussion_id, tag_id))
# Agregar usuario a la tabla discussion_user
cur_new.execute("""
INSERT IGNORE INTO fg_discussion_user (discussion_id, user_id)
VALUES (%s, %s)
""", (discussion_id, user_id))
conn_new.commit()
print(f"📝 Cuentos migrados: {len(cuentos)}")
# --------------------------
# Actualizar todos los contadores
# --------------------------
def update_all_counts():
# Actualizar contadores de discusiones para usuarios
cur_new.execute("""
UPDATE fg_users u
SET discussion_count = (
SELECT COUNT(*) FROM fg_discussions d WHERE d.user_id = u.id
)
""")
# Actualizar contadores de posts para usuarios
cur_new.execute("""
UPDATE fg_users u
SET comment_count = (
SELECT COUNT(*) FROM fg_posts p WHERE p.user_id = u.id AND p.type = 'comment'
)
""")
# Actualizar contador de discusiones para tags
cur_new.execute("""
UPDATE fg_tags t
SET discussion_count = (
SELECT COUNT(*) FROM fg_discussion_tag dt WHERE dt.tag_id = t.id
)
""")
conn_new.commit()
print("✅ Todos los contadores actualizados")
# --------------------------
# Ejecutar migración
# --------------------------
if __name__ == "__main__":
print("🚀 Iniciando migración completa...\n")
try:
user_map = migrate_users()
tag_id = get_literature_tag()
migrate_cuentos(user_map, tag_id)
update_all_counts()
print("\n🏁 Migración finalizada exitosamente!")
print("💡 No olvides limpiar la cache de Flarum:")
print(" php flarum cache:clear")
except Exception as e:
print(f"❌ Error durante la migración: {e}")
conn_new.rollback()
finally:
# Cerrar conexiones
cur_old.close()
cur_new.close()
conn_old.close()
conn_new.close()-----------------
2) Se hizo diagnostico:
import pymysql
import datetime
# --------------------------------
# Conexiones a las bases de datos
# --------------------------------
conn_old = pymysql.connect(
host="localhost",
user="root",
password="-----------",
database="fictograma_old",
cursorclass=pymysql.cursors.DictCursor
)
conn_new = pymysql.connect(
host="localhost",
user="forograma_user",
password="D---------",
database="forograma_db",
cursorclass=pymysql.cursors.DictCursor
)
def diagnosticar():
cur_new = conn_new.cursor()
print("=== DIAGNÓSTICO FLARUM ===")
# 1. Verificar si hay discusiones
cur_new.execute("SELECT COUNT(*) as count FROM fg_discussions")
disc_count = cur_new.fetchone()
print(f"1. Discusiones en la BD: {disc_count['count']}")
# 2. Verificar si hay posts
cur_new.execute("SELECT COUNT(*) as count FROM fg_posts")
post_count = cur_new.fetchone()
print(f"2. Posts en la BD: {post_count['count']}")
# 3. Verificar relación entre discusiones y posts
cur_new.execute("""
SELECT d.id, d.title, d.first_post_id, p.id as post_id, p.discussion_id, p.type, LENGTH(p.content) as content_length
FROM fg_discussions d
LEFT JOIN fg_posts p ON d.first_post_id = p.id
LIMIT 5
""")
relaciones = cur_new.fetchall()
print("3. Relaciones discusión-post (primeras 5):")
for rel in relaciones:
print(f" Discusión: {rel['title']}")
print(f" first_post_id: {rel['first_post_id']}, post_id: {rel['post_id']}")
print(f" discussion_id en post: {rel['discussion_id']}, type: {rel['type']}")
print(f" Longitud contenido: {rel['content_length']}")
# 4. Verificar contenido real de un post
if relaciones and relaciones[0]['post_id']:
cur_new.execute("SELECT content FROM fg_posts WHERE id = %s", (relaciones[0]['post_id'],))
contenido = cur_new.fetchone()
if contenido:
print(f"4. Contenido real del primer post (primeros 200 chars):")
print(f" '{contenido['content'][:200]}'")
# 5. Verificar estructura de tablas críticas
print("5. Estructura de fg_posts:")
cur_new.execute("DESCRIBE fg_posts")
estructura = cur_new.fetchall()
for campo in estructura:
print(f" {campo['Field']} - {campo['Type']}")
cur_new.close()
if __name__ == "__main__":
diagnosticar()
conn_old.close()
conn_new.close()
------------
3)El diagnóstico muestra el problema claramente. El campo type en todos los posts está como NULL en lugar de 'comment'. Este es el problema principal.
El contenido está en texto plano, no en formato XML.
4) Flarum está intentando procesar el contenido pero encuentra un problema con el formato XML. Revisemos y corrijamos el formato.
import pymysql
import datetime
import html
import re
--------------------------------
Conexiones a las bases de datos
--------------------------------
conn_new = pymysql.connect(
host="localhost",
user="forograma_user",
password="D---------",
database="forograma_db",
cursorclass=pymysql.cursors.DictCursor
)
cur_new = conn_new.cursor()
--------------------------
DEPURAR: Ver contenido actual
--------------------------
def debug_current_content():
print("=== DEPURACIÓN DE CONTENIDO ===")
# Ver algunos posts con su contenido actual
cur_new.execute("""
SELECT id, type,
LENGTH(content) as content_length,
LEFT(content, 200) as content_preview
FROM fg_posts
LIMIT 3
""")
posts = cur_new.fetchall()
for i, post in enumerate(posts):
print(f"\n--- Post {i+1} (ID: {post['id']}) ---")
print(f"Tipo: {post['type']}")
print(f"Longitud: {post['content_length']}")
print(f"Vista previa: {post['content_preview']}")
# Verificar si es XML válido
if post['content_preview'] and post['content_preview'].startswith('<?xml'):
print("✅ Formato: XML detectado")
else:
print("❌ Formato: No es XML")
--------------------------
FORMATO CORREGIDO para Flarum
--------------------------
def format_content_corrected(text):
"""
Formato EXACTO que Flarum espera - versión corregida
"""
if not text or not text.strip():
Contenido vacío - formato mínimo válido
return '<?xml version="1.0" encoding="utf-8"?><t></t>'
# Limpiar el texto
text = text.strip()
# ESCAPAR caracteres XML correctamente
# Primero reemplazar & para evitar doble escape
text = text.replace('&', '&')
text = text.replace('<', '<')
text = text.replace('>', '>')
text = text.replace('"', '"')
text = text.replace("'", ''')
# Manejar párrafos - Flarum usa <p> para párrafos
paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
if not paragraphs:
return '<?xml version="1.0" encoding="utf-8"?><t></t>'
# Construir el contenido XML
xml_paragraphs = []
for paragraph in paragraphs:
# Reemplazar saltos de línea simples por <break/>
paragraph = paragraph.replace('\n', '<break/>')
xml_paragraphs.append(f'<p>{paragraph}</p>')
content_body = ''.join(xml_paragraphs)
# Formato FINAL que Flarum espera
return f'<?xml version="1.0" encoding="utf-8"?><t>{content_body}</t>'
--------------------------
SOLUCIÓN ALTERNATIVA: Formato simple
--------------------------
def format_content_simple(text):
"""
Formato alternativo más simple que Flarum acepta
"""
if not text or not text.strip():
return '<?xml version="1.0" encoding="utf-8"?><t></t>'
text = text.strip()
# Escape básico
text = text.replace('&', '&')
text = text.replace('<', '<')
text = text.replace('>', '>')
# Usar <break/> para saltos de línea
text = text.replace('\n', '<break/>')
# Envolver en <p> simple
return f'<?xml version="1.0" encoding="utf-8"?><t><p>{text}</p></t>'
--------------------------
CORREGIR posts problemáticos
--------------------------
def fix_problematic_posts():
print("\n🔧 Corrigiendo posts problemáticos...")
# Primero: Revertir a texto plano temporalmente para diagnosticar
cur_new.execute("SELECT id, content FROM fg_posts WHERE content LIKE '<?xml%' LIMIT 5")
xml_posts = cur_new.fetchall()
print("Muestra de posts XML actuales:")
for post in xml_posts:
print(f"ID {post['id']}: {post['content'][:100]}...")
# Estrategia 1: Intentar con formato simple
print("\nAplicando formato simple...")
cur_new.execute("SELECT id, content FROM fg_posts WHERE content LIKE '<?xml%'")
all_posts = cur_new.fetchall()
fixed_count = 0
for post in all_posts:
# Extraer el texto original del XML si es posible
original_text = extract_text_from_xml(post['content'])
if not original_text:
continue
# Aplicar formato corregido
new_content = format_content_simple(original_text)
cur_new.execute("UPDATE fg_posts SET content = %s WHERE id = %s",
(new_content, post['id']))
fixed_count += 1
conn_new.commit()
print(f"✅ {fixed_count} posts actualizados con formato simple")
--------------------------
Extraer texto de XML (si es necesario)
--------------------------
def extract_text_from_xml(xml_content):
"""
Intenta extraer el texto limpio del XML existente
"""
if not xml_content or not xml_content.startswith('<?xml'):
return xml_content
# Remover la declaración XML
text = re.sub(r'<\?xml[^>]*\?>', '', xml_content)
# Remover tags <t>
text = re.sub(r'</?t>', '', text)
# Remover tags <p> y obtener contenido
text = re.sub(r'<p>(.*?)</p>', r'\1\n\n', text)
# Reemplazar <break/> con saltos de línea
text = text.replace('<break/>', '\n')
# Limpiar espacios extras
text = re.sub(r'\n\s*\n', '\n\n', text)
text = text.strip()
return text
--------------------------
SOLUCIÓN NUCLEAR: Resetear a texto plano
--------------------------
def nuclear_reset():
"""
Solución nuclear: Revertir todo a texto plano y dejar que Flarum lo formatee
"""
print("\n💥 APLICANDO SOLUCIÓN NUCLEAR...")
# 1. Obtener el texto original de la BD antigua
conn_old = pymysql.connect(
host="localhost",
user="root",
password="-----------",
database="fictograma_old",
cursorclass=pymysql.cursors.DictCursor
)
cur_old = conn_old.cursor()
cur_old.execute("SELECT id, titulo, descripcion, contenido FROM cuentos")
cuentos = cur_old.fetchall()
# Mapear por título (asumiendo que los títulos son únicos)
cuento_map = {}
for c in cuentos:
cuento_map[c['titulo']] = c
# 2. Para cada discusión en Flarum, encontrar el cuento correspondiente
cur_new.execute("""
SELECT d.id, d.title, p.id as post_id
FROM fg_discussions d
JOIN fg_posts p ON d.first_post_id = p.id
""")
discussions = cur_new.fetchall()
updated_count = 0
for disc in discussions:
if disc['title'] in cuento_map:
cuento = cuento_map[disc['title']]
# Reconstruir contenido
contenido = ""
if cuento.get('descripcion'):
contenido += cuento['descripcion'].strip() + "\n\n"
if cuento.get('contenido'):
contenido += cuento['contenido'].strip()
if contenido.strip():
# Usar formato MUY simple que Flarum pueda procesar
simple_content = f'<t>{contenido}</t>'
cur_new.execute("UPDATE fg_posts SET content = %s WHERE id = %s",
(simple_content, disc['post_id']))
updated_count += 1
print(f" ✅ Actualizado: {disc['title'][:30]}...")
conn_old.close()
conn_new.commit()
print(f"\n🎉 {updated_count} posts reseteados a texto original")
--------------------------
Ejecutar
--------------------------
if name == "main":
print("🚀 INICIANDO DEPURACIÓN Y REPARACIÓN...\n")
try:
# Paso 1: Depurar contenido actual
debug_current_content()
# Paso 2: Elegir estrategia
print("\n🔍 ¿Qué estrategia quieres probar?")
print("1. Formato simple corregido")
print("2. Solución nuclear (recomendado)")
# Por defecto, usar solución nuclear
print("\nUsando SOLUCIÓN NUCLEAR...")
nuclear_reset()
print("\n📋 PRÓXIMOS PASOS:")
print("1. Ejecuta: php flarum cache:clear")
print("2. Recarga tu foro Flarum")
print("3. Si sigue sin funcionar, revisa los logs:")
print(" - storage/logs/flarum.log")
print(" - Verifica permisos de archivos")
except Exception as e:
print(f"❌ ERROR: {e}")
import traceback
traceback.print_exc()
finally:
cur_new.close()
conn_new.close()
5) Processing instructions are not allowed". El problema es que Flarum no permite la declaración XML <?xml version="1.0" encoding="utf-8"?> en el contenido.
6)El problema es que el contenido se está escapando dos veces. Los caracteres HTML (<, >, &😉 deberían mostrarse como texto normal, no como código.
Aquí está el script corregido. SOLUCION!:
import pymysql
import datetime
# --------------------------------
# Conexiones a las bases de datos
# --------------------------------
conn_new = pymysql.connect(
host="localhost",
user="forograma_user",
password="D---------",
database="forograma_db",
cursorclass=pymysql.cursors.DictCursor
)
cur_new = conn_new.cursor()
# --------------------------
# FORMATEAR CONTENIDO CORRECTAMENTE
# --------------------------
def format_content_properly(text):
"""
Formatea el contenido para Flarum SIN doble escape
"""
if not text or not text.strip():
return '<t></t>'
text = text.strip()
# PRIMERO: Revertir cualquier escape previo
text = text.replace('&', '&')
text = text.replace('<', '<')
text = text.replace('>', '>')
text = text.replace('"', '"')
text = text.replace(''', "'")
# AHORA: Aplicar escape CORRECTO solo a caracteres especiales XML
# Pero mantener el HTML intacto para que Flarum lo procese
text = text.replace('&', '&')
# Solo escapar < y > que no sean parte de tags HTML válidos
import re
# Dividir en párrafos
paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
if not paragraphs:
return '<t></t>'
# Construir el contenido XML
xml_paragraphs = []
for paragraph in paragraphs:
# Reemplazar saltos de línea simples por <br/>
paragraph = paragraph.replace('\n', '<br/>')
# Escapar solo los < y > que no sean parte de tags HTML
# Esto es complejo, mejor usar un enfoque más simple:
paragraph = paragraph.replace('<', '<').replace('>', '>')
# Pero luego revertir los tags que queremos mantener
paragraph = paragraph.replace('<br/>', '<br/>')
paragraph = paragraph.replace('<br>', '<br/>')
xml_paragraphs.append(f'<p>{paragraph}</p>')
content_body = ''.join(xml_paragraphs)
return f'<t>{content_body}</t>'
# --------------------------
# SOLUCIÓN SIMPLE: Solo envolver en <t> sin escapes
# --------------------------
def format_content_simple(text):
"""
Envuelve el texto en <t> y convierte saltos de línea, pero sin escapar HTML
"""
if not text or not text.strip():
return '<t></t>'
text = text.strip()
# Revertir escapes previos si existen
text = text.replace('&', '&')
text = text.replace('<', '<')
text = text.replace('>', '>')
# Convertir saltos de línea dobles en párrafos
paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
if not paragraphs:
return '<t></t>'
# Si hay un solo párrafo, usar formato simple
if len(paragraphs) == 1:
# Convertir saltos de línea simples en <br>
content = paragraphs[0].replace('\n', '<br>')
return f'<t><p>{content}</p></t>'
# Múltiples párrafos
formatted_paragraphs = []
for paragraph in paragraphs:
paragraph = paragraph.replace('\n', '<br>')
formatted_paragraphs.append(f'<p>{paragraph}</p>')
content_body = ''.join(formatted_paragraphs)
return f'<t>{content_body}</t>'
# --------------------------
# SOLUCIÓN DEFINITIVA: Usar el formato de Flarum
# --------------------------
def format_content_flarum(text):
"""
Formato que Flarum usa internamente
"""
if not text or not text.strip():
return '<t></t>'
text = text.strip()
# Revertir cualquier escape previo
text = text.replace('&', '&')
text = text.replace('<', '<')
text = text.replace('>', '>')
# Flarum usa este formato específico:
# - <p> para párrafos
# - <br> para saltos de línea
# - Sin escape de HTML dentro de los párrafos
paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
if not paragraphs:
return '<t></t>'
formatted_paragraphs = []
for paragraph in paragraphs:
# Convertir saltos de línea dentro del párrafo
paragraph_html = paragraph.replace('\n', '<br>')
formatted_paragraphs.append(f'<p>{paragraph_html}</p>')
content_body = ''.join(formatted_paragraphs)
return f'<t>{content_body}</t>'
# --------------------------
# REPARAR TODOS LOS POSTS
# --------------------------
def fix_html_encoding():
print("🔧 Reparando encoding HTML en todos los posts...")
# 1. Verificar posts actuales
cur_new.execute("SELECT id, content FROM fg_posts WHERE content LIKE '%<%' OR content LIKE '%>%' OR content LIKE '%&%'")
encoded_posts = cur_new.fetchall()
print(f" Posts con HTML encoding: {len(encoded_posts)}")
# 2. Reparar cada post
updated_count = 0
for post in encoded_posts:
current_content = post['content']
# Extraer el texto real (sin formato XML)
if current_content.startswith('<t>') and current_content.endswith('</t>'):
inner_content = current_content[3:-4] # Remover <t> y </t>
# Revertir escapes HTML
clean_content = inner_content
clean_content = clean_content.replace('&', '&')
clean_content = clean_content.replace('<', '<')
clean_content = clean_content.replace('>', '>')
clean_content = clean_content.replace('"', '"')
clean_content = clean_content.replace(''', "'")
# Aplicar formato Flarum correcto
new_content = format_content_flarum(clean_content)
cur_new.execute("UPDATE fg_posts SET content = %s WHERE id = %s",
(new_content, post['id']))
updated_count += 1
conn_new.commit()
print(f" ✅ {updated_count} posts reparados con formato correcto")
# --------------------------
# VER EJEMPLO DE CONTENIDO
# --------------------------
def show_content_examples():
print("\n📝 Ejemplos de contenido actual:")
cur_new.execute("""
SELECT id, LEFT(content, 300) as content_sample
FROM fg_posts
WHERE content LIKE '%<%' OR content LIKE '%>%'
LIMIT 3
""")
examples = cur_new.fetchall()
for i, example in enumerate(examples):
print(f"\n--- Ejemplo {i+1} (ID: {example['id']}) ---")
print(example['content_sample'])
# --------------------------
# SOLUCIÓN COMPLETA
# --------------------------
def complete_fix():
print("🚀 APLICANDO SOLUCIÓN COMPLETA...")
# Paso 1: Mostrar ejemplos actuales
show_content_examples()
# Paso 2: Reparar encoding HTML
fix_html_encoding()
# Paso 3: Verificar resultado
print("\n🔍 Verificando resultado...")
cur_new.execute("SELECT COUNT(*) as count FROM fg_posts WHERE content LIKE '%<%' OR content LIKE '%>%'")
remaining_encoded = cur_new.fetchone()
print(f" Posts con HTML encoding restantes: {remaining_encoded['count']}")
# Paso 4: Mostrar ejemplos corregidos
cur_new.execute("""
SELECT id, LEFT(content, 300) as content_sample
FROM fg_posts
LIMIT 2
""")
corrected = cur_new.fetchall()
print("\n📝 Ejemplos de contenido corregido:")
for i, example in enumerate(corrected):
print(f"\n--- Corregido {i+1} (ID: {example['id']}) ---")
print(example['content_sample'])
# --------------------------
# EJECUCIÓN PRINCIPAL
# --------------------------
if __name__ == "__main__":
print("🎯 REPARANDO CARACTERES HTML...\n")
try:
complete_fix()
print("\n🎉 ¡REPARACIÓN COMPLETADA!")
print("\n📋 El contenido ahora debería mostrarse:")
print(" - Sin caracteres HTML visibles (<, >, &)")
print(" - Con párrafos y saltos de línea correctos")
print(" - Con el formato limpio y legible")
print("\n⚠️ Si aún ves problemas:")
print(" 1. Ejecuta: php flarum cache:clear")
print(" 2. Recarga la página con Ctrl+F5")
print(" 3. Verifica un post específico")
except Exception as e:
print(f"❌ ERROR: {e}")
import traceback
traceback.print_exc()
conn_new.rollback()
finally:
cur_new.close()
conn_new.close()
Disculpen la presentación pero las triples comillas del codigo se mezclan con las del BBC. Un saludo. PD. Aqui no se están migrando imágenes de discusiones ni avatares de perfiles ni comentarios, ni votos de la db anterior, solamente lo básico, perfiles (username, email.etc), y cuentos (titulos, posts, discussions). Este ultimo código es una 'reparación' del código primero.