How to Save a Python Dictionary in SQLAlchemy

Updated: January 3, 2024 By: Guest Contributor Post a comment

Overview

SQLAlchemy is a Python SQL toolkit and Object-Relational Mapping (ORM) library that allows developers to work with databases using Python objects. It adds a layer of abstraction over SQL, making database interactions more Pythonic and easy to understand.

Storing a Python dictionary in a database via SQLAlchemy involves mapping the dictionary to a database model. This tutorial guides you through the process, providing step-by-step code examples.

Before diving into code, you’ll need to ensure you have SQLAlchemy installed. You can install SQLAlchemy using pip:

pip install SQLAlchemy

Basic Dictionary Storage

Initially, let’s look at how to map a Python dictionary to a database.

from sqlalchemy import create_engine, Column, Integer, String, JSON
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class DataStore(Base):
    __tablename__ = 'data_store'

    id = Column(Integer, primary_key=True)
    my_dict = Column(JSON)

# Connect to the database
db_url = 'sqlite:///mydb.sqlite'
engine = create_engine(db_url)

# Create all tables
Base.metadata.create_all(engine)

# Create a session
Session = sessionmaker(bind=engine)
session = Session()

# Now, you can create instances of DataStore with a dictionary
data = {'key': 'value', 'another_key': 'another_value'}
data_store = DataStore(my_dict=data)
session.add(data_store)
session.commit()

Working with Nested Dictionaries

Serializing nested dictionaries is just as straightforward as simple ones.

data = {
    'outer_key': {
        'inner_key': 'value'
    }
}

# Just pass the nested dictionary to your model instance and commit
data_store = DataStore(my_dict=data)
session.add(data_store)
session.commit()

Querying Dictionary Data

Querying the database for your stored dictionary utilizes SQLAlchemy’s querying interface.

stored_data = session.query(DataStore).filter_by(id=1).first()
print(stored_data.my_dict)  # Will print the dictionary stored in the row with id = 1

Advanced Usage: Custom Serialization

If you need to store dictionaries in a database that doesn’t support JSON columns, you can serialize them manually.

import json

class DataStore(Base):
    __tablename__ = 'data_store'
    id = Column(Integer, primary_key=True)
    my_dict = Column(String)

    def __init__(self, **kwargs):
        kwargs['my_dict'] = json.dumps(kwargs.get('my_dict', {}))
        super().__init__(**kwargs)

    def dict(self):
        return json.loads(self.my_dict)

# Create tables and a session as before
data = {'key': 'value'}

# Serialize upon storing
my_entry = DataStore(my_dict=data)
session.add(my_entry)
session.commit()

# Deserialize upon querying
stored_entry = session.query(DataStore).first()
print(stored_entry.dict())

Handling Dynamic Dictionary Structures

When needing to handle dictionaries with dynamic keys, an adjunct table paired with a relationship can be employed.

from sqlalchemy import Table, ForeignKey
from sqlalchemy.orm import relationship

class DataStore(Base):
    # ... existing code ...
    entries = relationship('DataEntry', back_populates='data_store')

class DataEntry(Base):
    __tablename__ = 'data_entries'
    id = Column(Integer, primary_key=True)
    key = Column(String, nullable=False)
    value = Column(String, nullable=False)
    data_store_id = Column(Integer, ForeignKey('data_store.id'))

    data_store = relationship('DataStore', back_populates='entries')

# Create tables and session

# Storing a new dictionary
data_store = DataStore()
session.add(data_store)

for key, value in my_dict.items():
    entry = DataEntry(key=key, value=value, data_store=data_store)
    session.add(entry)

session.commit()

Performance Considerations

While JSON fields are convenient, bear in mind performance implications, especially when working with large datasets or high query volumes. Always profile and optimize your database interactions accordingly.

Conclusion

SQLAlchemy empowers developers to store and query Python dictionaries in SQL databases with ease. Utilize the provided examples to implement your solution, customizing it for your application’s needs. The power of SQLAlchemy lies in its flexibility and the high level of control it affords over database operations.