Sqlalchemy crea dinámicamente la tabla y la clase asignada

Dado un conjunto de nombres de columna y sus tipos, el objective es
para instanciar una tabla y la clase asignada correspondiente.

Está relacionado con la pregunta publicada aquí: Creación dinámica de clases en SQLAlchemy .

Hasta ahora tengo lo siguiente:

table = Table(tbl, metadata, *(Column(col, ctype, primary_key=pk, index=idx) for col, ctype, pk, idx in zip(attrs, types, primary_keys, indexes)) ) 

Esto crea el objeto de tabla. Ahora necesito crear la clase correspondiente.

 mydict={'__tablename__':tbl} cls = type(cls_name, (Base,), mydict) 

Esto me da el siguiente error:

ArgumentError: Mapper Mapper | persons_with_coord | t_persons_w_coord no pudo ensamblar ninguna columna de clave principal para la tabla asignada

Mi pregunta es cómo puedo especificar las claves primarias como parte de la creación de la clase. Y después de crear la clase, necesito llamar al asignador de la siguiente manera:

 mapper(cls, table) 

La asignación mydict debe incluir un objeto de tabla o especificar que la tabla debe cargarse desde la base de datos.

Esto debería funcionar

 mydict={'__tablename__':tbl, '__table__': table} 

Esto también debería funcionar

 mydict={'__tablename__':tbl, '__table_args__': ({'autoload':True},)} 

las claves primarias ya están especificadas al crear la table . No debería ser necesario especificarlos nuevamente cuando se crea un declarativo, sin embargo, si es necesario (por ejemplo, para una clave compleja), se debe especificar en __table_args__ .

El mapeador debe ser llamado en una clase declarativa. Sin embargo, el declarativo recién creado no tiene un objeto de metadatos. Agregar los metadatos hará que el declarativo creado dinámicamente se comporte más como un declarativo regular, por lo que recomendaría poner esta línea después de la creación de la clase.

 cls.metadata = cls.__table__.metadata 

Así, las ediciones completas podrían ser:

 mydict={'__tablename__':tbl, '__table__': table} cls = type(cls_name, (Base,), mydict) cls.metadata = cls.__table__.metadata