{"id":24732761,"url":"https://github.com/gonzalo123/flask_dbapi","last_synced_at":"2026-04-07T22:31:47.010Z","repository":{"id":152738140,"uuid":"625185019","full_name":"gonzalo123/flask_dbapi","owner":"gonzalo123","description":"Flask api skeleton to handle Postgresql operations","archived":false,"fork":false,"pushed_at":"2023-04-08T10:48:35.000Z","size":9,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-06T11:43:16.153Z","etag":null,"topics":["flask","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gonzalo123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-08T10:22:58.000Z","updated_at":"2023-06-25T15:22:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"2b2c2957-3c3e-448e-945d-31be09374367","html_url":"https://github.com/gonzalo123/flask_dbapi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gonzalo123/flask_dbapi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fflask_dbapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fflask_dbapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fflask_dbapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fflask_dbapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gonzalo123","download_url":"https://codeload.github.com/gonzalo123/flask_dbapi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gonzalo123%2Fflask_dbapi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31532215,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","python"],"created_at":"2025-01-27T17:53:58.911Z","updated_at":"2026-04-07T22:31:46.990Z","avatar_url":"https://github.com/gonzalo123.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Flask api skeleton to handle PostgreSQL operations\n\nThat`s a boilerplate for an api server using Flask. The idea is one api server to work as backend server to handle \nall database operations. The api server will handle only POST requests and the input parameters will be on the body \nof the payload as JSON. I know that it isn't a pure REST server but that's what I need.\n\nTo organize better the api we`ll set a group of modules using Flask's blueprints. The entry point of the application \nwill be app.py file\n\n```python\nimport logging\n\nfrom flask import Flask\nfrom flask_compress import Compress\n\nfrom lib.logger import setup_logging\nfrom lib.utils import CustomJSONEncoder\nfrom modules.example import blueprint as example\nfrom settings import LOG_LEVEL, ELK_APP, ELK_INDEX, ELK_PROCESS, LOG_PATH\n\nlogging.basicConfig(level=LOG_LEVEL)\n\nsetup_logging(app=ELK_APP,\n              index=ELK_INDEX,\n              process=ELK_PROCESS,\n              log_path=LOG_PATH)\n\napp = Flask(__name__)\napp.json_encoder = CustomJSONEncoder\ncompress = Compress()\ncompress.init_app(app)\n\napp.register_blueprint(example)\n```\nAll application configuration is in settings.py file. I borrow this pattern from Django applications. All my \nconfiguration is in this file and the particularities of the environment are loaded from dotenv files in settings.py  \n\n```python\nimport os\nfrom logging import INFO\nfrom pathlib import Path\n\nfrom dotenv import load_dotenv\n\nBASE_DIR = Path(__file__).resolve().parent\n\nAPP_ID = 'dbapi'\nAPP_PATH = 'dbapi'\nENVIRONMENT = os.getenv('ENVIRONMENT', 'local')\n\nload_dotenv(dotenv_path=Path(BASE_DIR).resolve().joinpath('env', ENVIRONMENT, '.env'))\n\nPROCESS_ID = os.getenv('PROCESS_ID', APP_ID)\nLOG_LEVEL = os.getenv('LOG_LEVEL', INFO)\nELK_APP = f'{APP_ID}.{PROCESS_ID}'\nELK_INDEX = f'{APP_ID}_{ENVIRONMENT}'\nELK_PROCESS = APP_ID\nLOG_PATH = f'./logs/{APP_ID}.log'\n\nBEARER = os.getenv('BEARER')\n\n# Database configuration\nDEFAULT = 'default'\n\nDATABASES = {\n    DEFAULT: f\"dbname='{os.getenv('DEFAULT_DB_NAME')}' user='{os.getenv('DEFAULT_DB_USER')}' host='{os.getenv('DEFAULT_DB_HOST')}' password='{os.getenv('DEFAULT_DB_PASS')}' port='{os.getenv('DEFAULT_DB_PORT')}'\"\n}\n```\n\nIn this example we're using one blueprint called example. I register blueprints manually. The blueprint has a set or \nroutes. Those routes are within routes.py file:\n\n```python\nfrom .actions import foo, bar\n\nroutes = [\n    dict(route='', action=lambda: True),\n    dict(route='foo', action=foo),\n    dict(route='bar', action=bar),\n]\n```\n\nHere we map url path to actions. For example foo action is like that\n\n\n```python\nfrom datetime import datetime\n\nfrom lib.decorators import use_schema\nfrom .schemas import FooSchema\n\n\n@use_schema(FooSchema)\ndef foo(name, email=False):\n    now = datetime.now()\n    return dict(name=name, email=email, time=now)\n```\n\nTo validate user input we're using schemas (using marshmallow library). In this example our validation schema is:\n\n```python\nfrom marshmallow import fields, Schema\n\n\nclass FooSchema(Schema):\n    name = fields.String(required=True)\n    email = fields.Email(required=False)\n```\n\nWe're hiding Flask infrastructure path in module's __init__.py file\n\n```python\nimport os\n\nfrom flask import Blueprint\n\nfrom lib.auth import authorize_bearer\nfrom lib.utils import call_action, get_response\nfrom settings import BEARER\nfrom .routes import routes\n\nNAME = os.path.basename(os.path.dirname(__file__))\nblueprint = Blueprint(NAME, __name__, url_prefix=f'/{NAME}')\n\n\n@authorize_bearer(bearer=BEARER)\n@blueprint.post('/')\n@blueprint.post('/\u003cpath:name\u003e')\ndef action(name=''):\n    return get_response(NAME, name, routes, call_action)\n```\n\nAnother route with a database connection is the following one:\n\n```python\nfrom dbutils import transactional\n\nfrom lib.db import get_db_from_conn, get_conn_from_dbname\nfrom lib.decorators import use_schema, inject_conn\nfrom settings import DEFAULT\nfrom .schemas import FooSchema\nfrom .sql import SQL_USERS\n\n\n@use_schema(FooSchema)\n@inject_conn(DEFAULT, named=True, autocommit=False)\ndef bar(conn, name, email=False):\n    # Create new transaction from connection injected with a decorator\n    with transactional(conn) as db:\n        db.upsert('users', dict(email=email), dict(name=name))\n\n    # Example of how to obtain new connection from database name.\n    conn2 = get_conn_from_dbname(DEFAULT)\n    db2 = get_db_from_conn(conn2)\n\n    return db2.fetch_all(SQL_USERS, dict(name=name))\n```\n\nWe can obtain our database connection from different ways. For example, we can use a function decorator to inject \nthe connection (in this case the connection named DEFAULT) in the function signatura. We also can create the \nconnection using a constructor. This connection is a raw psycopg2 connection. I also like to use a library to help \nme to work with psycopg2: a library (https://github.com/gonzalo123/dbutils) created by me time ago.\n\nAnd that's all. I normally deploy it in production using a nginx as a reverse proxy and n replicas of my api. Logs \nare also ready to send to ELK using a filebeat.\n\n```yaml\nversion: '3.6'\n\nx-logging: \u0026logging\n  logging:\n    options:\n      max-size: 10m\n\n\nservices:\n  api:\n    image: dbapi:production\n    \u003c\u003c: *logging\n    deploy:\n      replicas: 10\n      restart_policy:\n        condition: any\n    volumes:\n      - logs_volume:/src/logs\n    environment:\n      - ENVIRONMENT=production\n    command: /bin/bash ./start.sh\n\n  nginx:\n    image: nginx-dbapi:${VERSION}\n    deploy:\n      restart_policy:\n        condition: any\n    environment:\n      ENVIRON: ${VERSION}\n    ports:\n      - ${EXPOSED_PORT}:8000\n    depends_on:\n      - api\n\nvolumes:\n  logs_volume:\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgonzalo123%2Fflask_dbapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgonzalo123%2Fflask_dbapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgonzalo123%2Fflask_dbapi/lists"}