Python dicts en sqlalchemy

Me gustaría cargar / guardar un dictado en / desde mi base de datos sqlite, pero estoy teniendo algunos problemas para encontrar una manera simple de hacerlo. Realmente no necesito poder filtrar, etc., en función del contenido, por lo que una conversión simple a / desde la cadena está bien.

La siguiente mejor cosa sería las claves externas. Por favor, no publiques enlaces a grandes ejemplos, mi cabeza explotaría si alguna vez pongo los ojos en esos.

Puede crear un tipo personalizado mediante la subclase de sqlalchemy.types.TypeDecorator para manejar la serialización y deserialización a texto.

Una implementación podría parecer

 import json import sqlalchemy from sqlalchemy.types import TypeDecorator SIZE = 256 class TextPickleType(TypeDecorator): impl = sqlalchemy.Text(SIZE) def process_bind_param(self, value, dialect): if value is not None: value = json.dumps(value) return value def process_result_value(self, value, dialect): if value is not None: value = json.loads(value) return value 

Ejemplo de uso:

 class SomeModel(Base): __tablename__ = 'the_table' id = Column(Integer, primary_key=True) json_field = Column(TextPickleType()) s = SomeEntity(json_field={'baked': 'beans', 'spam': 'ham'}) session.add(s) session.commit() 

Esto se describe en un ejemplo en los documentos de SQLAlchemy , que también muestra cómo rastrear las mutaciones de ese diccionario.

Este enfoque debería funcionar para todas las versiones de Python, mientras que el simple hecho de pasar json como valor al argumento de PickleType no funcionará correctamente, como lo señala AlexGrönholm en su comentario sobre otra respuesta.

El SQLAlchemy PickleType está destinado exactamente para esto.

 class SomeEntity(Base): __tablename__ = 'some_entity' id = Column(Integer, primary_key=True) attributes = Column(PickleType) # Just set the attribute to save it s = SomeEntity(attributes={'baked': 'beans', 'spam': 'ham'}) session.add(s) session.commit() # If mutable=True on PickleType (the default) SQLAlchemy automatically # notices modifications. s.attributes['parrot'] = 'dead' session.commit() 

Puede cambiar el mecanismo de serialización cambiando el selector con otra cosa que tenga métodos de dumps() y de loads() . El mecanismo de almacenamiento subyacente subclasificando PickleType y anulando impl attritbute:

 class TextPickleType(PickleType): impl = Text import json class SomeOtherEntity(Base): __tablename__ = 'some_other_entity' id = Column(Integer, primary_key=True) attributes = Column(TextPickleType(pickler=json)) 

Si necesita mapear una relación 1-N y dict como dict lugar de list , entonces lea Colecciones basadas en diccionario

Pero si te refieres a un campo , entonces lo que puedes hacer es tener un campo DB de tipo cadena, que se asigna a tu objeto Python. Pero en el mismo objeto de Python, proporciona una propiedad que será una especie de proxy para este campo de cadena asignada de tipo dict (). Ejemplo de código (no probado):

 class MyObject(object): # fields (mapped automatically by sqlalchemy using mapper(...) MyFieldAsString = None def _get_MyFieldAsDict(self): if self.MyFieldAsString: return eval(self.MyFieldAsString) else: return {} # be careful with None and empty dict def _set_MyFieldAsDict(self, value): if value: self.MyFieldAsString = str(value) else: self.MyFieldAsString = None MyFieldAsDict = property(_get_MyFieldAsDict, _set_MyFieldAsDict)