{"id":14065301,"url":"https://github.com/siddhantgoel/flask-filealchemy","last_synced_at":"2025-08-19T21:31:40.434Z","repository":{"id":33135170,"uuid":"152702544","full_name":"siddhantgoel/flask-filealchemy","owner":"siddhantgoel","description":"YAML-formatted plain-text file based models for Flask backed by Flask-SQLAlchemy","archived":false,"fork":false,"pushed_at":"2024-12-02T06:49:02.000Z","size":602,"stargazers_count":24,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-02T07:33:00.891Z","etag":null,"topics":["flask","python","python3","sqlalchemy","static-site","web","yaml"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/siddhantgoel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","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},"funding":{"github":"siddhantgoel"}},"created_at":"2018-10-12T06:13:45.000Z","updated_at":"2024-12-02T06:49:00.000Z","dependencies_parsed_at":"2023-10-15T07:24:12.923Z","dependency_job_id":"815b6d5b-ca23-4014-bdde-d004b38cf5c2","html_url":"https://github.com/siddhantgoel/flask-filealchemy","commit_stats":{"total_commits":244,"total_committers":4,"mean_commits":61.0,"dds":0.3483606557377049,"last_synced_commit":"7b44a1d0327f59d6b0856100bd9c33636448b000"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siddhantgoel%2Fflask-filealchemy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siddhantgoel%2Fflask-filealchemy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siddhantgoel%2Fflask-filealchemy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siddhantgoel%2Fflask-filealchemy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siddhantgoel","download_url":"https://codeload.github.com/siddhantgoel/flask-filealchemy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230367928,"owners_count":18215338,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","python3","sqlalchemy","static-site","web","yaml"],"created_at":"2024-08-13T07:04:25.214Z","updated_at":"2025-08-19T21:31:40.420Z","avatar_url":"https://github.com/siddhantgoel.png","language":"Python","funding_links":["https://github.com/sponsors/siddhantgoel"],"categories":["Python"],"sub_categories":[],"readme":"# Flask-FileAlchemy\n\n![](https://github.com/siddhantgoel/flask-filealchemy/workflows/flask-filealchemy/badge.svg) ![](https://badge.fury.io/py/flask-filealchemy.svg)\n\n`Flask-FileAlchemy` is a [Flask] extension that lets you use Markdown or YAML\nformatted plain-text files as the main data store for your apps.\n\n## Installation\n\n```bash\n$ pip install flask-filealchemy\n```\n\n## Background\n\nThe constraints on which data-store to use for applications that only have to\nrun locally are quite relaxed as compared to the ones that have to serve\nproduction traffic. For such applications, it's normally OK to sacrifice on\nperformance for ease of use.\n\nOne very strong use case here is generating static sites. While you can use\n[Frozen-Flask] to \"freeze\" an entire Flask application to a set of HTML files,\nyour application still needs to read data from somewhere. This means you'll need\nto set up a data store, which (locally) tends to be file based SQLite. While\nthat does the job extremely well, this also means executing SQL statements to\ninput data.\n\nDepending on how many data models you have and what types they contain, this can\nquickly get out of hand (imagine having to write an `INSERT` statement for a\nblog post).\n\nIn addition, you can't version control your data. Well, technically you can, but\nthe diffs won't make any sense to a human.\n\nFlask-FileAlchemy lets you use an alternative data store - plain text files.\n\nPlain text files have the advantage of being much easier to handle for a human.\nPlus, you can version control them so your application data and code are both\nchecked in together and share history.\n\nFlask-FileAlchemy lets you enter your data in Markdown or YAML formatted plain\ntext files and loads them according to the [SQLAlchemy] models you've defined\nusing [Flask-SQLAlchemy] This data is then put into whatever data store you're\nusing (in-memory SQLite works best) and is then ready for your app to query\nhowever it pleases.\n\nThis lets you retain the comfort of dynamic sites without compromising on the\nsimplicity of static sites.\n\n## Usage\n\n### Define data models\n\nDefine your data models using the standard (Flask-)SQLAlchemy API. As an\nexample, a `BlogPost` model can defined as follows.\n\n```python\napp = Flask(__name__)\n\n# configure Flask-SQLAlchemy\napp.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'\n\ndb = SQLAlchemy()\n\ndb.init_app(app)\n\nclass BlogPost(db.Model):\n   __tablename__ = 'blog_posts'\n\n   slug = Column(String(255), primary_key=True)\n   title = Column(String(255), nullable=False)\n   content = Column(Text, nullable=False)\n```\n\n### Add some data\n\nNext, create a `data/` directory somewhere on your disk (to keep things simple,\nit's recommended to have this directory in the application root). For each model\nyou've defined, create a directory under this `data/` directory with the same\nname as the `__tablename__` attribute.\n\nWe currently support three different ways to define data.\n\n#### 1. Multiple YAML files\n\nThe first way is to have multiple YAML files inside the `data/\u003c__tablename__\u003e/`\ndirectory, each file corresponding to one record.\n\nIn case of the \"blog\" example, we can define a new `BlogPost` record by creating\nthe file `data/blog_posts/first-post-ever.yml` with the following content.\n\n```yaml\nslug: first-post-ever\ntitle: First post ever!\ncontent: |\n  This blog post talks about how it's the first post ever!\n```\n\nAdding more such files in the same directory would result in more records.\n\n#### 2. Single YAML file\n\nFor \"smaller\" models which don't have more than 2-3 fields, Flask-FileAlchemy\nsupports reading from an `_all.yml` file. In such a case, instead of adding one\nfile for every row, simply add all the rows in the `_all.yml` file inside the\ntable directory.\n\nFor the \"blog\" example, this would look like the following.\n\n```yaml\n- slug: first-post-ever\n  title: First post ever!\n  content: This blog post talks about how it's the first post ever!\n\n- slug: second-post-ever\n  title: second post ever!\n  content: This blog post talks about how it's the second post ever!\n ```\n\n#### 3. Markdown/Frontmatter\n\nIt's also possible to load data from Jekyll-style Markdown files containing\nFrontmatter metadata.\n\nIn case of the blog example, it's possible to create a new `BlogPost` record by\ndefining a `data/blog_posts/first-post-ever.md` file with the following\ncontent.\n\n```markdown\n---\nslug: first-post-ever\ntitle: First post ever!\n---\n\nThis blog post talks about how it's the first post ever!\n```\n\nPlease note that when defining data using markdown, the name of the column\nassociated with the main markdown body **needs** to be `content`.\n\n#### 4. Configure and load\n\nFinally, configure `Flask-FileAlchemy` with your setup and ask it to load all\nyour data.\n\n```python\n# configure Flask-FileAlchemy\napp.config['FILEALCHEMY_DATA_DIR'] = os.path.join(\n   os.path.dirname(os.path.realpath(__file__)), 'data'\n)\napp.config['FILEALCHEMY_MODELS'] = (BlogPost,)\n\n# load tables\nFileAlchemy(app, db).load_tables()\n```\n\n`Flask-FileAlchemy` then reads your data from the given directory, and stores\nthem in the data store of your choice that you configured `Flask-FileAlchemy`\nwith (the preference being `sqlite:///:memory:`).\n\nPlease note that it's not possible to write to this database using `db.session`.\nWell, technically it's allowed, but the changes your app makes will only be\nreflected in the in-memory data store but won't be persisted to disk.\n\n## Contributing\n\nContributions are most welcome!\n\nPlease make sure you have Python 3.9+ and [uv] installed.\n\n1. Git clone the repository -\n   `git clone https://github.com/siddhantgoel/flask-filealchemy`.\n\n2. Install the packages required for development - `uv sync`.\n\n3. That's basically it. You should now be able to run the test suite -\n   `uv run pytest`.\n\n[Flask-SQLAlchemy]: https://flask-sqlalchemy.palletsprojects.com/\n[Flask]: https://flask.palletsprojects.com/\n[Frozen-Flask]: https://pythonhosted.org/Frozen-Flask/\n[SQLAlchemy]: https://www.sqlalchemy.org/\n[uv]: https://docs.astral.sh/uv/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiddhantgoel%2Fflask-filealchemy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiddhantgoel%2Fflask-filealchemy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiddhantgoel%2Fflask-filealchemy/lists"}