¿Existe alguna forma en SQLAlchemy de crear un proxy de un campo JSON de pares clave/valor para que actúe como columnas individuales?
Mi situación es similar a la de los ejemplos de Mapeo de Atributos Verticales cubiertos en la documentación de SQLAlchemy. Sin embargo, los nombres de las columnas y los valores se almacenan en un campo JSON como un diccionario. Los tipos de cada columna se almacenan en otra tabla con otro campo JSON (clave/valor, la clave es el nombre del campo y el valor es el tipo de campo).
¿Es posible crear un proxy de asociación que trate el diccionario del campo ‘kwargs’ como columnas individuales y consultables?
class MainClass(db.Model):
__tablename__ = "main_class"
id = db.Column(db.Integer, primary_key=True)
...
# {"nombre_campo1": "str", "nombre_campo2": "int", "nombre_campo3": "bool", "nombre_campo4": "list"}
valid_kwargs = db.Column(db.JSON, nullable=False, default=dict())
class ChildClass(db.Model):
__tablename__ = "child_class"
id = db.Column(db.Integer, primary_key=True)
main_class_id = db.Column(db.Integer, db.ForeignKey("main_class.id"))
...
# {"nombre_campo1": "test", "nombre_campo2": 1, "nombre_campo3": False, "nombre_campo4": ["a", "b", "c"]}
kwargs = db.Column(db.JSON, nullable=False, default=dict())
davy.ai
Sí, es posible crear un proxy de asociación que trate el diccionario del campo
kwargs
como columnas individuales consultables. Usando la extensiónGenericAttributes
de SQLAlchemy, podemos asignar dinámicamente los campos JSON a columnas en nuestro modelo.Aquí hay un ejemplo de implementación:
En este ejemplo, estamos utilizando el tipo
MutableDict
de SQLAlchemy para crear un campo JSON que se puede actualizar directamente en el modelo. También estamos utilizando la extensiónGenericAttributes
para asignar dinámicamente los campos JSON a columnas en nuestro modelo.La clase
Attribute
asigna los nombres y tipos de columnas a un “entity_type” (ya sea “main_class” o “child_class”), lo que nos permite tener diferentes tipos de columnas para cada tabla.Las clases
MainClass
yChildClass
definen métodos__getattr__
que devuelven el valor adecuado del campo JSON si el atributo no está definido en la clase.El método
association_proxy
crea un proxy que nos permite tratar el diccionario JSON como columnas individuales que se pueden consultar directamente.En general, esta implementación nos permite almacenar y consultar datos JSON como si fueran una columna regular en nuestro modelo.