Crafting a Cocktail API: Mastering CRUD with Flask, SQLAlchemy and Flask-RESTful

GabrielleGabrielle
3 min read

If you’re building a full-stack app with Flask, one of the first skills you’ll need is CRUD — Create, Read, Update, and Delete. These four operations form the foundation of any backend API, and with Flask-RESTful, you can organize your routes in a clean, reusable way. In this post, I’ll walk through how to implement CRUD functionality using Flask, SQLAlchemy, and Flask-RESTful — a handy extension that helps organize your routes in a clean, class-based format.


Setting Up the Model

First, let’s define a simple SQLAlchemy model called Cocktail. This model represents a cocktail recipe with a name and a base spirit. We'll also define __tablename__, which explicitly sets the name of the table in the database — a good practice, especially when using migrations.

# models.py
# ...import statements

class Cocktail(db.Model):
    __tablename__ = 'cocktails'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    spirit = db.Column(db.String, nullable=False)
    ingredients = db.Column(db.String, nullable=False)
    instructions = db.Column(db.String, nullable=False)

    def to_dict(self):
        return {
            "id": self.id,
            "name": self.name,
            "spirit": self.spirit,
            "ingredients": self.ingredients,
            "instructions": self.instructions
        }

The to_dict() method is used to serialize our model data into a format we can return in API responses.

Note: Flask-SQLAlchemy 3.1+ includes a built-in to_dict() method, but we're defining our own to_dict() method here.


Creating the Resource Class

Instead of writing separate route functions, Flask-RESTful allows us to organize all HTTP methods into class-based views. This improves readability and makes your code easier to maintain.

Handling All Cocktails (GET, POST)

# app.py

# Remote library imports
from flask import request
from flask_restful import Resource

# Local imports
from config import app, db, api
# Add your model imports
from models import Cocktail

class CocktailResource(Resource):

    def get(self):
        cocktails = Cocktail.query.all()
        return [c.to_dict() for c in cocktails], 200

    def post(self):
        json = request.get_json()
        new_cocktail = Cocktail(name=json['name'], spirit=json['spirit'])
        db.session.add(new_cocktail)
        db.session.commit()
        return new_cocktail.to_dict(), 201

The get() method retrieves all cocktails from the database. The post() method allows a client to submit a new cocktail via JSON and have it saved to the database.

Handling a Single Cocktail (GET, PATCH, DELETE)

class CocktailByID(Resource):
    def get(self, id):
        cocktail = Cocktail.query.filter_by(id=id).first()
        return cocktail.to_dict(), 200

    def patch(self, id):
        cocktail = Cocktail.query.filter_by(id=id).first()
        json = request.get_json()
        if 'name' in json:
            cocktail.name = json['name']
        if 'spirit' in json:
            cocktail.spirit = json['spirit']
        db.session.commit()
        return cocktail.to_dict(), 200

    def delete(self, id):
        cocktail = Cocktail.query.filter_by(id=id).first()
        db.session.delete(cocktail)
        db.session.commit()
        return '', 204

These methods allow us to fetch, update, or delete a single cocktail based on its id.


Registering the Resources

To make these resource classes available in your Flask app, you’ll need to register them with the API object:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_restful import Api
from models import db
from resources import CocktailsResource, CocktailByID

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'

db.init_app(app)
api = Api(app)

api.add_resource(CocktailsResource, '/cocktails')
api.add_resource(CocktailByID, '/cocktails/<int:id>')

Note: In a full project, you'd likely also configure CORS, Migrate, and Bcrypt for things like frontend connections, database migrations, and user authentication. For this post, we’re focusing on CRUD and keeping the setup minimal.

With this setup, your backend now supports full CRUD operations via:

  • GET /cocktails → list all cocktails

  • POST /cocktails → create a new cocktail

  • GET /cocktails/<id> → get one cocktail

  • PATCH /cocktails/<id> → update a cocktail

  • DELETE /cocktails/<id> → delete a cocktail

You can test these routes using Postman, or wire them up to a frontend app using JavaScript fetch()


Conclusion

CRUD is the foundation of almost every backend application. Using Flask-RESTful with SQLAlchemy allowed me to build a clean and maintainable API that supported full data interaction in my cocktail recipe app. Once I understood how to structure models and route logic into resource classes, adding new features became much easier.

Whether you're building a recipe manager, to-do app, or anything that stores and updates data, mastering CRUD in Flask is a crucial step — and using Flask-RESTful is one of the best ways to organize it.

0
Subscribe to my newsletter

Read articles from Gabrielle directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Gabrielle
Gabrielle