Подтвердить что ты не робот

Python прописывает в sqlalchemy

Я хотел бы загрузить/сохранить dict в/из моей базы данных sqlite, но у меня возникли проблемы с выяснением простого способа сделать это. Мне действительно не нужно фильтровать и т.д. На основе содержимого, поэтому простое преобразование в/из строки в порядке.

Следующим лучшим было бы иностранные ключи. Пожалуйста, не публикуйте ссылки на огромные примеры, моя голова взорвется, если я когда-нибудь посмотрю на них.

4b9b3361

Ответ 1

Вы можете создать настраиваемый тип путем подкласса sqlalchemy.types.TypeDecorator для обработки сериализации и десериализации в Text.

Реализация может выглядеть как

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

Пример использования:

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()

Это описано в примере в документах SQLAlchemy, в котором также показано, как отслеживать мутации этого словаря.

Этот подход должен работать для всех версий Python, тогда как просто передача json в качестве значения аргумента pickler PickleType будет работать некорректно, поскольку точки AlexGrönholm вне в своем комментарии к другому ответу.

Ответ 2

SQLAlchemy PickleType предназначен именно для этого.

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()

Вы можете изменить механизм сериализации, заменив сортировщик на что-то еще, имеющее методы dumps() и loads(). Основной механизм хранения путем подклассификации PickleType и переопределения 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))

Ответ 3

Если вам нужно сопоставить отношение 1-N и сопоставить его как dict, а не list, тогда прочитайте Коллекции, основанные на словарях

Но если вы имеете в виду поле , то что вы можете сделать, чтобы иметь поле БД строки типа, которое отображается на ваш объект Python. Но на одном и том же объекте python вы предоставляете свойство, которое будет своеобразным прокси для этого отображаемого строкового поля типа dict(). Пример кода (не проверен):

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)