Skip to main content

Easy to use JSON serialization and update/create for Flask and SQLAlchemey.

Project description


PyPI Version

DB Model JSON serialization with PUT, POST write for Flask applications using SQLAlchemy

Simple and quick to get going in two steps.

  1. Import and add the FlaskSerializeMixin mixin to a model:

from flask_serialize import FlaskSerializeMixin

class Item(db.Model, FlaskSerializeMixin):
    id = db.Column(db.Integer, primary_key=True)
    # other fields ...
  1. Configure the route with the do all mixin method:

def items(item_id=None):
    return Item.get_delete_put_post(item_id)
  1. Done! Returns JSON as a single item or a list with only a single route.

Flask-serialize is intended for joining a Flask SQLAlchemy Python backend with a JavaScript Web client. It allows read JSON serialization from the db and easy to use write back of models using PUT and POST.

4 times faster than marshmallow for simple dict serialization.

It is not suitable for two way serialization. Use marshmallow or similar for more complicated systems.


Model setup:

# example database model
from flask_serialize import FlaskSerializeMixin

# required to set class var db for writing to a database
from app import db

FlaskSerializeMixin.db = db

class Setting(FlaskSerializeMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)

    setting_type = db.Column(db.String(120), index=True, default='misc')
    key = db.Column(db.String(120), index=True)
    value = db.Column(db.String(30000), default='')
    active = db.Column(db.String(1), default='y')
    created = db.Column(db.DateTime, default=datetime.utcnow)
    updated = db.Column(db.DateTime, default=datetime.utcnow)

    # serializer fields
    create_fields = update_fields = ['setting_type', 'value', 'key', 'active']

    # checks if Flask-Serialize can delete
    def can_delete(self):
        if self.value == '1234':
            raise Exception('Deletion not allowed.  Magic value!')

    # checks if Flask-Serialize can create/update
    def verify(self, create=False):
        if not self.key or len(self.key) < 1:
            raise Exception('Missing key')

        if not self.setting_type or len(self.setting_type) < 1:
            raise Exception('Missing setting type')

    def __repr__(self):
        return '<Setting %r %r %r>' % (, self.setting_type, self.value)

Routes setup:

Get a single item as json.

@app.route('/get_setting/<item_id>', methods=['GET'])
def get_setting( item_id ):
    return Setting.get_delete_put_post(item_id)

Returns a Flask response with a json object, example:
{id:1, value: "hello"}

Put an update to a single item as json.

@app.route('/update_setting/<item_id>', methods=['PUT'])
def update_setting( item_id ):
    return Setting.get_delete_put_post(item_id)

Returns a Flask response with the result as a json object:
{error:"any error message", message: "success message"}

Delete a single item.

@app.route('/delete_setting/<item_id>', methods=['DELETE'])
def delete_setting( item_id ):
    return Setting.get_delete_put_post(item_id)

Returns a Flask response with the result as a json object:
{error:"any error message", message: "success message"}

Get all items as a json list.

@app.route('/get_setting_all', methods=['GET'])
def get_setting_all():
    return Setting.get_delete_put_post()

Returns a Flask response with a list of json objects, example:
[{id:1, value: "hello"},{id:2, value: "there"},{id:3, value: "programmer"}]

All of: get-all, get, put, post, and delete can be combined in one route.

@app.route('/setting/<int:item_id>', methods=['GET', 'PUT', 'DELETE', 'POST'])
@app.route('/setting', methods=['GET', 'POST'])
def route_setting_all(item_id=None):
    return Setting.get_delete_put_post(item_id)

Updating from a json object in the flask put request

JQuery example:

function put(setting_id) {
    try {
        return $.ajax({
            url: `/update_setting/${setting_id}`,
            method: 'PUT',
            contentType: "application/json",
            data: {setting_type:"x",value:"100"},
        }).then(response => {
    } catch (e) {
        alert(`Error updating ${e.message}`);

Flask route:

@app.route('/update_setting/<int:item_id>', methods=['PUT'])
def update_setting(item_id):
    return Setting.get_delete_put_post(item_id)

Create or update from a WTF form:

@app.route('/setting_edit/<int:item_id>', methods=['POST'])
@app.route('/setting_add', methods=['POST'])
def setting_edit(item_id=None):
    if item_id:
        item = Setting.query.get_or_404(item_id)
        item = {}
    form = EditForm(obj=item)

    if form.validate_on_submit():
        if item_id:
                flash('Your changes have been saved.')
            except Exception as e:
                flash(str(e), category='danger')
            return redirect(url_for('setting_edit', item_id=item_id))
                new_item = Setting.request_create_form()
                flash('Setting created.')
                return redirect(url_for('setting_edit',
            except Exception as e:
                flash('Error creating item: ' + str(e))

    return render_template(
            title='Edit or Create item',

Create a child database object:

As example: add a Stat object to a Survey object using the request_create_form convenience method. The foreign key to the parent Survey is provided as a kwargs parameter to the method.

@app.route('/stat/<int:survey_id>', methods=['POST'])
def stat_add(survey_id=None):
    survey = Survey.query.get_or_404(survey_id)
    return Stat.request_create_form(


Exclude fields

List of model field names to not serialize at all.

exclude_serialize_fields = []

List of model field names to not serialize when return as json.

exclude_json_serialize_fields = []

Verify write and create

def verify(self, create=False):
    raise exception if item is not valid for put/patch/post
    :param: create - True if verification is for a new item

Override the mixin verify method to provide control and verification when updating and creating model items. Simply raise an exception when there is a problem. You can also modify self data before writing. See model example.

Controlling delete

def can_delete(self):
    raise exception if item cannot be deleted

Override the mixin can_delete to provide control over when an item can be deleted. Simply raise an exception when there is a problem. See model example.

Updating fields specification

List of model fields to be read from a form or JSON when updating an object. Normally admin fields such as login_counts or security fields are excluded.

update_fields = []

Update Properties

When returning a success code from a put or post update a dict composed of the property values from the update_properties list is returned as “properties”.

update_properties = []

Example return JSON:

class ExampleModel(db.Model, FlaskSerializeMixin):
    update_fields = ['hat_size']

    def hat_size(self):
        return self.head_size * self.ear_width
// result update return message
{message: "Updated", properties: {new_hat_size: 45.67} }

This can be used to communicate from the model on the server to the JavaScript code interesting things from updates

Creation fields used when creating specification

List of model fields to be read from a form when creating an object.

create_fields = []

Filtering json list results

Json result lists can be filtered by using the prop_filters on either the get_delete_put_post method or the json_list method.

The filter consists of one or more properties in the json result and the value that it must match. Filter items will match against the first prop_filter property to exactly equal the value.


result = get_delete_put_post(prop_filters = {'key':'dogs'})

Sorting json list results

Json result lists can be sorted by using the order_by_field or the order_by_field_desc properties. To sort by id ascending use this example:

order_by_field = 'id'

Update DateTime fields specification

timestamp_fields is a list of fields on the model to be set when updating or creating with the value of datetime.datetime.utcnow(). The default field names to update are: [‘timestamp’, ‘updated’].


class ExampleModel(db.Model, FlaskSerializeMixin):
    # ....
    modified = db.Column(db.DateTime, default=datetime.utcnow)
    timestamp_fields = ['modified']

Override the timestamp default of utcnow() by replacing the timestamp_stamper class property with your own. Example:

class ExampleModel(db.Model, FlaskSerializeMixin):
    # ....
    timestamp_stamper =

Relationships list of property names that are to be included in serialization

relationship_fields = []

In default operation relationships in models are not serialized. Add any relationship property name here to be included in serialization.

Serialization converters

There are three built in converters to convert data from the database to a good format for serialization:

  • DATETIME - Removes the fractional second part and makes it a string

  • PROPERTY - Enumerates and returns model added properties

  • RELATIONSHIP - Deals with children model items.

Set one of these to None or a value to remove or replace it’s behaviour.

Adding and overriding converter behaviour

Add values to the class property:

column_type_converters = {}

Where the key is the column type name of the database column and the value is a method to provide the conversion.


To convert VARCHAR(100) to a string:

column_type_converters['VARCHAR(100)'] = lambda v: str(v)

To change DATETIME conversion behaviour, either change the DATETIME column_type_converter or override the to_date_short method of the mixin. Example:

import time

class Model(db.model, FlaskSerializeMixin):
    # ...
    # ...
    def to_date_short(self, date_value):
        convert a datetime.datetime type to
        a unix like milliseconds since epoch
        :param date_value: datetime.datetime {object}
        :return: number
        if not date_value:
            return 0

        return int(time.mktime(date_value.timetuple())) * 1000

Conversion types (to database) add or replace update/create

Add or replace to db conversion methods by using a list of dicts that specify conversions.

Default is:

convert_types = [{'type': bool, 'method': lambda v: 'y' if v else 'n'}]
  • type: a python object type

  • method: a lambda or method to provide the conversion to a database acceptable value.

Mixin Helper methods and properties

get_delete_put_post(item_id, user, prop_filters)

Put, get, delete, post and get-all magic method handler.

  • item_id: the primary key of the item - if none and method is ‘GET’ returns all items

  • user: user to user as query filter.

  • prop_filters: dictionary of key:value pairs to limit results when returning get-all.




returns one item when item_id is a primary key


returns all items when item_id is None


updates item using item_id as the id from request json data. Calls the model verify before updating.


removes the item with primary key of item_id if self.can_delete does not throw an error


creates and returns a Flask response with a new item as json from form body data or JSON body data when item_id is None. Calls the model verify before creating.


updates an item from form data using item_id. Returns json response of {‘message’:’something’, ‘error’:’any error message’}. Calls the model verify before updating.

On error returns a response of ‘error message’ with http status code of 400.

Set the user parameter to restrict a certain user. Assumes that a model relationship of user exists.

Prop filters is a dictionary of property name:value pairs. Ie: {‘group’: ‘admin’} to restrict list to the admin group. Properties or database fields can be used as the property name.


def as_dict(self):
    the sql object as a dict without the excluded fields
    :return: dict


def as_json(self):
    the sql object as a json object without the excluded dict and json fields
    :return: json object


def dict_list(cls, query_result):
    return a list of dictionary objects from the sql query result
    :param query_result: sql alchemy query result
    :return: list of dict objects


Return a flask response in json format from a sql alchemy query result.

def json_list(cls, query_result):
    return a list in json format from the query_result
    :param query_result: sql alchemy query result
    :return: flask response with json list of results


@bp.route('/address/list', methods=['GET'])
def address_list():
    items = Address.query.filter_by(user=current_user)
    return Address.json_list(items)


Return a flask list response in json format using a filter_by query.

def json_filter_by(cls, **kwargs):
    return a list in json format using the filter_by arguments
    :param kwargs: SQLAlchemy query.filter_by arguments
    :return: flask response with json list of results


@bp.route('/address/list', methods=['GET'])
def address_list():
    return Address.filter_by(user=current_user)


Return the first result in json format using filter_by arguments.


@bp.route('/score/<course>', methods=['GET'])
def score(course):
    return Score.json_first(class_name=course)


Use the contents of a Flask request form or request json data to create a item in the database. Calls verify(create=True). Returns the new item or throws error. Use kwargs to set the object properties of the newly created item.


Create a score item with the parent being a course.

@bp.route('/score/<course_id>', methods=['POST'])
def score(course_id):
    course = Course.query.get_or_404(course_id)
    return Score.request_create_form(


Use the contents of a Flask request form or request json data to update an item in the database. Calls verify(). Returns True on success.


Update a score item.


@bp.route('/score/<int:score_id>', methods=['PUT'])
def score(score_id):
    score = Score.query.get_or_404(score_id)
    if Score.request_update_form():
        return 'ok'
        return 'update failed'

Release Notes

  • 1.1.2 - Add 400 http status code for errors, remove error dict. Improve documentation.

  • 1.1.0 - Suppress silly errors. Improve documentation.

  • 1.0.9 - Add kwargs to request_create_form to pass Object projects to be used when creating the Object instance

  • 1.0.8 - Cache introspection to improve performance. All model definitions are cached after first use to improve performance. It is no longer possible to alter model definitions dynamically.

  • 1.0.7 - Add json body support to post update.

  • 1.0.5 - Allow sorting of json lists.


  • Apache 2.0

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release. See tutorial on generating distribution archives.

Built Distribution

flask_serialize-1.1.2-py2.py3-none-any.whl (15.7 kB view hashes)

Uploaded py2 py3

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Huawei Huawei PSF Sponsor Microsoft Microsoft PSF Sponsor NVIDIA NVIDIA PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page