Serialization with SQLAlchemy and Flask
If you google what serialization means, it's:
the process of converting data into a format suitable for transmission and storage
Before we dive deeper into what serializing your data is, here is a general explanation of what flask and sqlalchemy is since we will be using them for our serialization purposes. Flask is a framework that provides out of the box configuration to get up and running without having to do too much setup. It allows you to create routes to retrieve requested data from a server. SQLAlchemy is an ORM (Object Relational Mapper) tool used to communicate with your database and maps your instances to a table.
SERIALIZATION
Think of serialization like the way puzzles are made and sold. When a puzzle is created, it's originally one big picture. In order to deliver the puzzle to you, the manufacturer can't send you the entire picture as one piece. Instead, the manufacturer breaks down the picture into smaller pieces, then delivers the box to you. When you receive the box, you can open it and then assemble the pieces back to its original form using the picture on the box as a guide
Similarly, serialization in programming takes complex information (like a whole database or an object) and breaks it down into a simpler, more transportable format (like the puzzle pieces). This makes it easier to save onto a hard drive, send over the internet, or pass data between programs and computers. When needed, this data can be 'assembled' back into its original, complex form, just like putting puzzle pieces together to form the picture on the box.
There are many libraries and resources to use when it comes to serializing your data but today I will be focusing on just two of them: SerializerMixin and Marshmallow. I'll share some example of how you can use them and explain some important considerations when deciding which one would work best for your project.
Let's build a one-to-many relationship where one user can have many services.
class User(db.Model):
__tablename__ = 'authors'
serialize_rules = ('-services.user',)
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
#relationships
services = db.relationship('Service', back_populates='user', cascade='all, delete-orphan')
class Service(db.Model):
__tablename__ = 'books'
serialize_rules = ('-services.user',)
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, nullable=False)
#relationship
user = db.relationship('User', back_populates='services')
SerializerMixin
Now that we have our models, if you haven't already, install sqlalchemy_serializer:
pip install SQLAlchemy-serializer
Then import SerializerMixin:
from sqlalchemy_serializer import SerializerMixin
In your models, pass SerializerMixin:
class Model(SerializerMixin):
pass
Your code should look something like this:
from sqlalchemy_serializer import SerializerMixin
class User(db.Model, SerializerMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
#relationships
services = db.relationship('Service', back_populates='user', cascade='all, delete-orphan')
class Service(db.Model, SerializerMixin):
__tablename__ = 'services'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, nullable=False)
#relationship
user = db.relationship('User', back_populates='services')
Now we can start formatting our data using the serialize rules in our models.
from sqlalchemy_serializer import SerializerMixin
class User(db.Model, SerializerMixin):
__tablename__ = 'authors'
serialize_rules = ('-services.user',)
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
#relationships
services = db.relationship('Service', back_populates='user', cascade='all, delete-orphan')
class Service(db.Model, SerializerMixin):
__tablename__ = 'books'
serialize_rules = ('-user.services',)
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, nullable=False)
#relationship
user = db.relationship('User', back_populates='services')
SerializerMixin
focuses on simplifying serialization within SQLAlchemy models, while Marshmallow offers a broader range of serialization and validation features for various data structures.
Marshmallow
Install Marshmallow:
pip install flask-marshmallow
Here is a link to configure marshmallow in your project before continuing.
In Marshmallow, you serialize your data in the routes. Whereas with SerializerMixin, you serialize your data in the models.
In the Routes:
#Marshmallow Schema's for Users and Services
class UserSchema(ma.Schema):
class Meta:
model = User
load_instance = True
id = ma.Integer()
name = ma.String()
class ServiceSchema(ma.Schema):
class Meta:
model = Service
load_instance = True
title = ma.String()
#if you want a nested object from a model.Nested method
#this will include the user who owns the service
user = fields.Nested(UserSchema)
id = ma.Number()
url = ma.Hyperlinks(
{
"collection": ma.URLFor("services")
}
)
services_schema = ServiceSchema(many=True)
class Services(Resource):
def get(self):
services = Service.query.all()
#services_schema.dump is like .to_dict() from SerializeMixin
results = services_schema.dump(services)
return results, 200
api.add_resource(Services, '/services', endpoint='services')
Marshmallow is designed for complex data serialization and deserialization in various formats. As you can see in the code above, you have more flexibility and control over what attributes you want included in the object returned when the route is hit. services_schema = ServiceSchema(many=True)
lets marshmallow know that a collection of objects need to be serialized instead of just one. Remove many=True
when your serializing a single object. Marshmallow makes it easier to manage complex data structures and it's used for applications that require detailed control over serializing your data.
SerializerMixin is for simpler applications that don't need to much control over serializing data. Customization and validation is limited and there's not much flexibility.
With marshmallow you have more control over formatting your data and you can decide what you want to return. SerializerMixin works best for simple applications with a minimal setup. Using Marshmallow and SerializeMixin depends on your project's needs, the complexity of your data serialization, and how much control you need over the serialization process.