API REST con Python, Flask y SQLite3

En este tutorial de programación con Python aprenderás a crear una API REST usando Flask, SQLite 3 (para los datos) y JSON para la comunicación de datos.

Al final tendrás una API que puedes consumir desde cualquier cliente, ya sea una aplicación para Android, un navegador con JavaScript o incluso otro lenguaje de servidor.

Te mostraré cómo crear una API que se comunica usando JSON y guarda los datos en SQLite 3. La API estará creada con Flask, y usaremos el lenguaje de programación Python para manejar todos los datos.

Descripción de la API

API con Flask y Python

Vamos a usar los 4 verbos HTTP más usados: GET, POST, PUT y DELETE, mismos que estarán relacionados con el CRUD de la base de datos.

Lo que vamos a gestionar será una base de datos de juegos, mismos que tienen nombre, precio y calificación. También tendremos varias operaciones que vamos a exponer a través de la API creada con Flask:

  • Obtener todos los juegos
  • Crear un nuevo juego
  • Actualizar un juego
  • Eliminar un juego
  • Obtener un juego por ID

Primero vamos a crear el CRUD que se relaciona con la base de datos usando Python, y más tarde vamos a exponer todas estas funciones con Flask, ya en la API, codificando como JSON.

Base de datos SQLite3

La estructura de la base de datos queda como se ve a continuación. Es una única tabla, aunque a partir de este tutorial podemos crear más tablas, relaciones, etcétera.

CREATE TABLE IF NOT EXISTS games(
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  price REAL NOT NULL,
  rate INTEGER NOT NULL
)

Después vemos el archivo de conexión a la base de datos:

import sqlite3
DATABASE_NAME = "games.db"


def get_db():
    conn = sqlite3.connect(DATABASE_NAME)
    return conn


def create_tables():
    tables = [
        """CREATE TABLE IF NOT EXISTS games(
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
				price REAL NOT NULL,
				rate INTEGER NOT NULL
            )
            """
    ]
    db = get_db()
    cursor = db.cursor()
    for table in tables:
        cursor.execute(table)

En este archivo de conexión SQLite3 con Python observamos que la base de datos se llamará games.db. Además, contamos con dos funciones: una de ellas es para obtener la base de datos, y la otra (create_tables) es para crear las tablas dentro de la base de datos solo en caso de que no existan.

Fíjate bien en estas funciones, pues las vamos a importar desde otros archivos. Ahora que ya tenemos definida la base de datos veamos el CRUD de juegos con la base de datos SQLite3.

Controlador de juegos: conexión a base de datos

Antes de exponer la base de datos en la API, vamos a crear un controlador de juegos que se va a encargar de todas las operaciones para guardar, actualizar, eliminar y obtener los datos de los juegos.

Todas estas funciones se encuentran dentro de un archivo llamado game_controller.py y se ve así:

from db import get_db


def insert_game(name, price, rate):
    db = get_db()
    cursor = db.cursor()
    statement = "INSERT INTO games(name, price, rate) VALUES (?, ?, ?)"
    cursor.execute(statement, [name, price, rate])
    db.commit()
    return True


def update_game(id, name, price, rate):
    db = get_db()
    cursor = db.cursor()
    statement = "UPDATE games SET name = ?, price = ?, rate = ? WHERE id = ?"
    cursor.execute(statement, [name, price, rate, id])
    db.commit()
    return True


def delete_game(id):
    db = get_db()
    cursor = db.cursor()
    statement = "DELETE FROM games WHERE id = ?"
    cursor.execute(statement, [id])
    db.commit()
    return True


def get_by_id(id):
    db = get_db()
    cursor = db.cursor()
    statement = "SELECT id, name, price, rate FROM games WHERE id = ?"
    cursor.execute(statement, [id])
    return cursor.fetchone()


def get_games():
    db = get_db()
    cursor = db.cursor()
    query = "SELECT id, name, price, rate FROM games"
    cursor.execute(query)
    return cursor.fetchall()

En el archivo vemos varias funciones. La función insert_game recibe los datos del juego y los inserta en la base de datos (INSERT); todo esto usando sentencias preparadas para evitar inyecciones SQL en esta API que estamos creando con Python y Flask.

También vemos otros métodos como update_game que realiza la operación UPDATE para actualizar un juego, delete_game que elimina un juego (DELETE) a partir de su id, get_by_id que regresa un juego a partir de su id (usando la operación SELECT).

Finalmente observamos la función get_games que devuelve todos los juegos existentes.

Fíjate en que todas las funciones usan la base de datos y un cursor para realizar todas las operaciones.

Ahora que ya tenemos el CRUD de las operaciones con la base de datos es momento de exponer todo en la API con Flask.

Creando API con Flask y Python

Lo primero que hacemos en la API es crear la app de Flask e importar el controlador de los juegos. También importamos una función de la base de datos porque necesitamos crear las tablas al iniciar la aplicación:

from flask import Flask, jsonify, request
import game_controller
from db import create_tables

app = Flask(__name__)

Ahora definimos las rutas con los verbos GET, PUT, POST y DELETE:



@app.route('/games', methods=["GET"])
def get_games():
    games = game_controller.get_games()
    return jsonify(games)


@app.route("/game", methods=["POST"])
def insert_game():
    game_details = request.get_json()
    name = game_details["name"]
    price = game_details["price"]
    rate = game_details["rate"]
    result = game_controller.insert_game(name, price, rate)
    return jsonify(result)


@app.route("/game", methods=["PUT"])
def update_game():
    game_details = request.get_json()
    id = game_details["id"]
    name = game_details["name"]
    price = game_details["price"]
    rate = game_details["rate"]
    result = game_controller.update_game(id, name, price, rate)
    return jsonify(result)


@app.route("/game/<id>", methods=["DELETE"])
def delete_game(id):
    result = game_controller.delete_game(id)
    return jsonify(result)


@app.route("/game/<id>", methods=["GET"])
def get_game_by_id(id):
    game = game_controller.get_by_id(id)
    return jsonify(game)

Cada ruta expone una función del controlador de juegos que vimos anteriormente, que a su vez interactúa con la base de datos de SQLite3. Es importante destacar algunas cosas. Por ejemplo, al actualizar e insertar un juego leemos el JSON de la petición con get_json y accedemos al diccionario.

En el caso de eliminar o de obtener por ID leemos la variable id desde la ruta como <variable> y recibiéndola en el método.

También fíjate en que esta API con Python se comunica a través de JSON, por lo que todas las respuestas se hacen de acuerdo a lo que regresa la función jsonify.

Finalmente creamos la app de Flask para iniciar el servidor y escuchar peticiones:

if __name__ == "__main__":
    create_tables()
    """
    Here you can change debug and port
    Remember that, in order to make this API functional, you must set debug in False
    """
    app.run(host='0.0.0.0', port=8000, debug=False)

Opcional: agregar CORS

Si vas a consumir esta API desde un dominio distinto al de la misma, necesitas habilitar CORS. Basta con agregar el siguiente fragmento de código en la API (en el repositorio encontrarás el código ya agregado, mismo que puedes remover si quieres):

"""
Enable CORS. Disable it if you don't need CORS
"""
@app.after_request
def after_request(response):
    response.headers["Access-Control-Allow-Origin"] = "*" # <- You can change "*" for a domain for example "http://localhost"
    response.headers["Access-Control-Allow-Credentials"] = "true"
    response.headers["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS, PUT, DELETE"
    response.headers["Access-Control-Allow-Headers"] = "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"
    return response


Poniendo todo junto

El código completo de la API queda así:

"""
    API REST con Python 3 y SQLite 3
    By Parzibyte: 
    ** https://parzibyte.me/blog **
"""
from flask import Flask, jsonify, request
import game_controller
from db import create_tables

app = Flask(__name__)


@app.route('/games', methods=["GET"])
def get_games():
    games = game_controller.get_games()
    return jsonify(games)


@app.route("/game", methods=["POST"])
def insert_game():
    game_details = request.get_json()
    name = game_details["name"]
    price = game_details["price"]
    rate = game_details["rate"]
    result = game_controller.insert_game(name, price, rate)
    return jsonify(result)


@app.route("/game", methods=["PUT"])
def update_game():
    game_details = request.get_json()
    id = game_details["id"]
    name = game_details["name"]
    price = game_details["price"]
    rate = game_details["rate"]
    result = game_controller.update_game(id, name, price, rate)
    return jsonify(result)


@app.route("/game/<id>", methods=["DELETE"])
def delete_game(id):
    result = game_controller.delete_game(id)
    return jsonify(result)


@app.route("/game/<id>", methods=["GET"])
def get_game_by_id(id):
    game = game_controller.get_by_id(id)
    return jsonify(game)


if __name__ == "__main__":
    create_tables()
    """
    Here you can change debug and port
    Remember that, in order to make this API functional, you must set debug in False
    """
    app.run(host='0.0.0.0', port=8000, debug=False)

Si quieres ver el código de los otros archivos y el repositorio completo, visita mi GitHub. Ahí podrás descargar y probar todo el código open source.

Recuerda que para iniciar el servidor y la API debes ejecutar:

python main.py

O en su defecto:

python3 main.py

Probando API

Después de clonar y ejecutar el repositorio puedes realizar las pruebas usando Postman o cualquier lenguaje de tu preferencia. Más adelante traeré ejemplos de consumo con Frameworks JavaScript o con JavaScript puro.

Mientras tanto te dejo una captura probando la API:

Consumiendo API REST creada con Flask y Python usando SQLite y JSON

Si te gusta Python, te invito a leer más contenido de ese tema en mi blog. O aprende más sobre Flask.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

1 comentario en “API REST con Python, Flask y SQLite3”

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *