{"id":24890672,"url":"https://github.com/skulltech/ormvana","last_synced_at":"2026-04-13T18:01:25.322Z","repository":{"id":57449610,"uuid":"144173610","full_name":"skulltech/ormvana","owner":"skulltech","description":"A minimalist ORM for the power user — Releases you from the sufferings of the traditional ORM world.","archived":false,"fork":false,"pushed_at":"2019-01-19T09:25:53.000Z","size":23,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-19T04:03:49.625Z","etag":null,"topics":["database","mysql","orm","python","python3","sql","sqlite3"],"latest_commit_sha":null,"homepage":"https://ormvana.readthedocs.io/","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/skulltech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-09T15:46:29.000Z","updated_at":"2019-01-20T16:08:13.000Z","dependencies_parsed_at":"2022-09-14T10:51:54.801Z","dependency_job_id":null,"html_url":"https://github.com/skulltech/ormvana","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/skulltech/ormvana","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skulltech%2Formvana","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skulltech%2Formvana/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skulltech%2Formvana/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skulltech%2Formvana/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skulltech","download_url":"https://codeload.github.com/skulltech/ormvana/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skulltech%2Formvana/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31764317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T15:25:13.801Z","status":"ssl_error","status_checked_at":"2026-04-13T15:25:09.162Z","response_time":93,"last_error":"SSL_read: 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":["database","mysql","orm","python","python3","sql","sqlite3"],"created_at":"2025-02-01T17:17:27.964Z","updated_at":"2026-04-13T18:01:25.295Z","avatar_url":"https://github.com/skulltech.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ormvana\nA minimalist ORM for the power user — Releases you from the sufferings of the traditional ORM world.\n\n[![PyPI version](https://badge.fury.io/py/ormvana.svg)](https://badge.fury.io/py/ormvana)\n\n## Usage\n\nUsing `ormvana` is as simple as:\n```python\nfrom ormvana import Model\n\nclass User(Model):\n    name = 'user'\n    fields = dict()\n    for field in ['email', 'first_name', 'last_name']:\n        fields[field] = {'type': str}\n    fields['active'] = {\n        'type': int,\n        'value': 0\n    }\n    \njohn = User(email='john@email.com', first_name='John', last_name='Doe')\njohn.save()\njohn.email = 'john@email.io'\njohn.save()\n```\n\n## Features\n\n- Model based ORM, similar to most popular framework, so nonexistent learning curve.\n- Create, modify and fetch records easily using built-in implementations.\n- Complete freedom over database schema — it lets you create the schema yourself.\n- Complete freedom over writing custom SQL queries.\n\n## Installation\n\nInstall it using pip\n```console\n$ pip3 install ormvana\n```\n\n## Documentation\n\nDocumentation is available at https://ormvana.readthedocs.io/\n\n## Tutorial\n\nI'm going to demonstrate the usage of this module using a blog application, containing two tables: users and posts. You \ncan find the complete example [here](https://github.com/SkullTech/ormvana/tree/master/example/).\n\n### Defining the models\n\nTo get started, all you need to do is —\n- Create class(es) describing the `Model` // `Table`(s).\n- Provide a function which \nreturns a connection to a database. \n\nFor example\n```sql\nCREATE TABLE IF NOT EXISTS user (\n id INTEGER PRIMARY KEY,\n email TEXT NOT NULL,\n first_name TEXT NOT NULL,\n last_name INTEGER NOT NULL,\n active INTEGER NOT NULL DEFAULT '0'\n);\n```\n\nFor the above database `Table` definition, you should create a `Model` class like the following —\n\n```python\nfrom ormvana import Model\n\nclass User(Model):\n    name = 'user'\n    fields = dict()\n    for field in ['email', 'first_name', 'last_name']:\n        fields[field] = {'type': str}\n    fields['active'] = {\n        'type': int,\n        'value': 0\n    }\n```\n\nNotice that all we're really doing is:\n- Specifying the name of the `Table` using the `name` class variable.\n- Specifying the columns // `Field`s of the database using the `fields` class variable. `fields` is a dict, where the \nkeys are the _field names_ and the values are dicts. These dicts necessarily contain a key named `type` which can either take \n`str` or `int` as values, and optionally contain another key named `value`, which can be used to provide a default \nvalue of the given field.\n\nYou also would need to provide a `connection` function to `ormvana`, which would return a connection to the database, \nalong with a bool that indicates whether to `close` the connection after every query.\n\nCheck the following example:\n```python\nimport sqlite3\nimport ormvana\n\ndef connection():\n    conn = sqlite3.connect('blog.db')\n    conn.row_factory = sqlite3.Row\n    return True, conn\n\normvana.connection = connection\n```\n\nFor retrieving records // objects, _ormvana_ provides you with three built-in class functions — \n1. `get`: For retrieving record by `id`. \n2. `get_by`: For retrieving records(s) having given value for given field.\n3. `get_all`: For retrieving all the records of the table.\n\nFor everything else, you have to write a method for your class that returns a valid SQL query, and decorate that with \neither the `fetch_single` or `fetch_multiple` decorator accordingly. For example, look at the following:\n\n```sql\nDROP TABLE IF EXISTS `post`;\nCREATE TABLE IF NOT EXISTS post (\n  id INTEGER PRIMARY KEY,\n  title TEXT NOT NULL,\n  body TEXT NOT NULL,\n  author INTEGER NOT NULL\n);\n```\n\n```python\nfrom ormvana import Model\n\nclass Post(Model):\n    name = 'post'\n    fields = dict()\n    for field in ['title', 'body']:\n        fields[field] = {'type': str}\n    fields['author'] = {'type': int}\n\n    @classmethod\n    @Model.fetch_multiple\n    def users_posts(cls, email):\n        return '''SELECT * FROM `{0}` WHERE `author`=(SELECT id from `user` WHERE email='{1}');'''.format(cls.name,\n                                                                                                          email)\n```\n\nNow that we have defined our models, let's look at how we could use them in our application.\n\n### Creating records\n\n```pycon\n\u003e\u003e\u003e from models import User, Post\n\u003e\u003e\u003e john = User(email='john@email.com', first_name='John', last_name='Doe')\n\u003e\u003e\u003e john.save()\n[*] Query: INSERT INTO `user` (`active`, `email`, `first_name`, `last_name`) VALUES (0, 'john@email.com', 'John', 'Doe');\n1\n\u003e\u003e\u003e john.email = 'john@email.io'\n\u003e\u003e\u003e john.save()\n[*] Query: UPDATE `user` set `active` = 0, `email` = 'john@email.io', `first_name` = 'John', `last_name` = 'Doe' WHERE id=1;\n1\n\u003e\u003e\u003e jane = User(email='jane@email.com', first_name='Jane', last_name='Doe', active=1)\n\u003e\u003e\u003e jane.save()\n[*] Query: INSERT INTO `user` (`active`, `email`, `first_name`, `last_name`) VALUES (1, 'jane@email.com', 'Jane', 'Doe');\n2\n\u003e\u003e\u003e post = Post(title='Hello world!', body='This is my first post!', author=1)\n\u003e\u003e\u003e post\n{'id': '', 'cnx': \u003csqlite3.Connection object at 0x01055B20\u003e, 'title': 'Hello world!', 'body': 'This is my first post!', 'author': 1}\n\u003e\u003e\u003e post.save()\n[*] Query: INSERT INTO `post` (`title`, `body`, `author`) VALUES ('Hello world!', 'This is my first post!', 1);\n1\n```\n\n### Updating records\n\n```pycon\n\u003e\u003e\u003e john.email = 'john@email.io'\n\u003e\u003e\u003e john.save()\n[*] Query: UPDATE `user` set `active` = 0, `email` = 'john@email.io', `first_name` = 'John', `last_name` = 'Doe' WHERE id=1;\n1\n```\n\n### Retrieving records\n\n```pycon\n\u003e\u003e\u003e from models import User, Post\n\u003e\u003e\u003e users = User.get_all()\n[*] Query: SELECT * FROM `user`;\n\u003e\u003e\u003e users\n[{'id': 1, 'cnx': \u003csqlite3.Connection object at 0x01D059A0\u003e, 'email': 'john@email.io', 'first_name': 'John', 'last_name': 'Doe', 'active': 0}, {'id': 2, 'cnx': \u003csqlite3.Connection object at 0x01D05A20\u003e, 'email': 'jane@email.com', 'first_name': 'Jane', 'last_name': 'Doe', 'active': 1}]\n\u003e\u003e\u003e users[0].first_name\n'John'\n\u003e\u003e\u003e jane = User.get(2)\n[*] Query: SELECT * FROM `user` WHERE id='2';\n\u003e\u003e\u003e jane\n{'id': 2, 'cnx': \u003csqlite3.Connection object at 0x01D05CA0\u003e, 'email': 'jane@email.com', 'first_name': 'Jane', 'last_name': 'Doe', 'active': 1}\n\u003e\u003e\u003e results = User.get_by('first_name', 'John')\n[*] Query: SELECT * FROM `user` WHERE first_name='John';\n\u003e\u003e\u003e results\n[{'id': 1, 'cnx': \u003csqlite3.Connection object at 0x010559A0\u003e, 'email': 'john@email.io', 'first_name': 'John', 'last_name': 'Doe', 'active': 0}]\n\u003e\u003e\u003e Post.users_posts('john@email.io')\n[*] Query: SELECT * FROM `post` WHERE `author`=(SELECT id from `user` WHERE email='john@email.io');\n[{'id': 1, 'cnx': \u003csqlite3.Connection object at 0x03885CA0\u003e, 'title': 'Hello world!', 'body': 'This is my first post!', 'author': 1}]\n```\n\n## Contribute\n\nAll kinds of contribution are welcome.\n\n- Issue Tracker — https://github.com/ormvana/issues\n- Source Code — https://github.com/ormvana\n\n## License\n\nThis project is licensed under the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskulltech%2Formvana","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskulltech%2Formvana","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskulltech%2Formvana/lists"}