saffier


Namesaffier JSON
Version 1.3.7 PyPI version JSON
download
home_page
SummaryThe only python ORM you will ever need.
upload_time2024-03-08 11:38:58
maintainer
docs_urlNone
author
requires_python>=3.8
license
keywords api asgi fastapi framework http machine learning ml openapi pydantic rest starlette websocket
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Saffier

<p align="center">
  <a href="https://saffier.tarsild.io"><img src="https://res.cloudinary.com/dymmond/image/upload/v1675104815/Saffier/logo/logo_dowatx.png" alt='Saffier'></a>
</p>

<p align="center">
    <em>🚀 The only Async ORM you need. 🚀</em>
</p>

<p align="center">
<a href="https://github.com/tarsil/saffier/workflows/Test%20Suite/badge.svg?event=push&branch=main" target="_blank">
    <img src="https://github.com/tarsil/saffier/workflows/Test%20Suite/badge.svg?event=push&branch=main" alt="Test Suite">
</a>

<a href="https://pypi.org/project/saffier" target="_blank">
    <img src="https://img.shields.io/pypi/v/saffier?color=%2334D058&label=pypi%20package" alt="Package version">
</a>

<a href="https://pypi.org/project/saffier" target="_blank">
    <img src="https://img.shields.io/pypi/pyversions/saffier.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>

---

**Documentation**: [https://saffier.tarsild.io](https://saffier.tarsild.io) 📚

**Source Code**: [https://github.com/tarsil/saffier](https://github.com/tarsil/saffier)

---

## Motivation

Almost every project, in one way or another uses one (or many) databases. An ORM is simply an mapping
of the top of an existing database. ORM extends for Object Relational Mapping and bridges object-oriented
programs and relational databases.

Two of the most well known ORMs are from Django and SQLAlchemy. Both have their own strengths and
weaknesses and specific use cases.

This ORM is built on the top of SQLAlchemy core and aims to simplify the way the setup and queries
are done into a more common and familiar interface.

## Before continuing

If you are looking for something more **Pyadntic** oriented where you can take literally advantage
of everything that Pydantic can offer, then instead of continuing with Saffier, have a look at
its ***data ORM brother***, [Edgy](https://edgy.tarsild.io).

**Edgy** its extremely powerful as well with a key difference that its **100% Pydantic** which means
you can leverage the technology if you already familiar with it.

No worries, it is not completely different from Saffier, in fact, it was designed with the same principles and what it changes for you
are essentially the ***imports***.

### Thinking of moving to Edgy?

If you are considering of moving to Edgy but you don't want to be bothered about learning a new
tool and afraid of breaking changes, then fear not!

Edgy was designed to also make your migration feel seemless, which means that essentially you would
only need to install it and change the imports in your project from `saffier` to `edgy` and it should
work automatically for you.

Even the documentation structure its almost the same, intentionally, so what you already know with
Saffier, you will know with **Edgy**.

**This discards any custom code done by you, of course.**

## Why this ORM

When investigating for a project different types of ORMs and compared them to each other, for a lot
of use cases, SQLAlchemyalways took the win but had an issue, the async support (which now there
are a few solutions). While doing the research I came across [Encode ORM](https://www.encode.io/orm/).

The team is the same behind of Databases, Django Rest Framework, Starlette,
httpx and a lot more tools used by millions.

There was one issue though, although ORM was doing a great familiar interface with SQLAlchemy and
providing the async solution needed, it was, by the time of this writing, incomplete and they
even stated that in the documentation and that is how **Saffier** was born.

Saffier uses some of the same concepts of ORM from Encode but rewritten in **Pydantic** but not all.

## Saffier

Saffier is some sort of a fork from [Encode ORM](https://www.encode.io/orm/) but rewritten at its
core and with a complete set of tools with a familiar interface to work with.
If you are familiar with Django, then you came for a treat 😄.

Saffier leverages the power of **Pydantic** for its fields while offering a friendly, familiar and
easy to use interface.

This ORM was designed to be flexible and compatible with pretty much every ASGI framework, like
[Esmerald](https://esmerald.dymmond.com), Starlette, FastAPI, Sanic, Quart... With simple pluggable
design thanks to its origins.

### Special notes

Saffier couldn't exist without [Encode ORM](https://www.encode.io/orm/) and the continous work
done by the amazing team behind it. For that reason, thank you!

## Features

While adopting a familiar interface, it offers some cool and powerful features on the top of
SQLAlchemy core.

### Key features

* **Model inheritance** - For those cases where you don't want to repeat yourself while maintaining
intregity of the models.
* **Abstract classes** - That's right! Sometimes you simply want a model that holds common fields
that doesn't need to created as a table in the database.
* **Meta classes** - If you are familiar with Django, this is not new to you and Saffier offers this
in the same fashion.
* **Managers** - Versatility at its core, you can have separate managers for your models to optimise
specific queries and querysets at ease.
* **Filters** - Filter by any field you want and need.
* **Model operators** - Classic operations such as `update`, `get`, `get_or_none`, `bulk_create`,
`bulk_update` and a lot more.
* **Relationships made it easy** - Support for `OneToOne` and `ForeignKey` in the same Django style.
* **Constraints** - Unique constraints through meta fields.
* **Native test client** - We all know how hard it can be to setup that client for those tests you
need so we give you already one.
* **Multi-tenancy** - Saffier supports multi-tenancy and even offers a possible solution to be used
out of the box if you don't want to waste time.

And a lot more you can do here.

## Migrations

Since **Saffier**, like [Encode ORM](https://www.encode.io/orm/), is built on the top of
[SQLAlchemy core](https://docs.sqlalchemy.org/en/20/core/), it brings its own native migration
system running on the top of [Alembic](https://alembic.sqlalchemy.org/en/latest/) but making it a
lot easier to use and more pleasant for you.

Have a look at the [migrations](https://saffier.tarsild.io/migrations.md) for more details.

## Installation

To install Saffier, simply run:

```shell
$ pip install saffier
```

You can pickup your favourite database driver by yourself or you can run:

**Postgres**

```shell
$ pip install saffier[postgres]
```

**MySQL/MariaDB**

```shell
$ pip install saffier[mysql]
```

**SQLite**

```shell
$ pip install saffier[sqlite]
```

## Quick Start

The following is an example how to start with **Saffier** and more details and examples can be
found throughout the documentation.

**Use** `ipython` **to run the following from the console, since it supports** `await`.

```python
import saffier
from saffier import Database, Registry

database = Database("sqlite:///db.sqlite")
models = Registry(database=database)


class User(saffier.Model):
    """
    The User model to be created in the database as a table
    If no name is provided the in Meta class, it will generate
    a "users" table for you.
    """

    id = saffier.IntegerField(primary_key=True)
    is_active = saffier.BooleanField(default=False)

    class Meta:
        registry = models


# Create the db and tables
# Don't use this in production! Use Alembic or any tool to manage
# The migrations for you
await models.create_all()

await User.query.create(is_active=False)

user = await User.query.get(id=1)
print(user)
# User(id=1)

```

As stated in the example, if no `tablename` is provided in the `Meta` class, Saffier automatically
generates the name of the table for you by pluralising the class name.

## Connect your application

Do you want to have more complex structures and connect to your favourite framework? Have a look
at [connections](https:/saffier.tarsild.io/connection.md) to understand how to do it properly.

**Exciting!**

In the documentation we go deeper in explanations and examples, this was just to warm up. 😁

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "saffier",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "api,asgi,fastapi,framework,http,machine learning,ml,openapi,pydantic,rest,starlette,websocket",
    "author": "",
    "author_email": "Tiago Silva <tiago.arasilva@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/89/89/27eb76c9e4bf8dede12a2044edc00c958a9f2d4fc89b459cd55d20af244d/saffier-1.3.7.tar.gz",
    "platform": null,
    "description": "# Saffier\n\n<p align=\"center\">\n  <a href=\"https://saffier.tarsild.io\"><img src=\"https://res.cloudinary.com/dymmond/image/upload/v1675104815/Saffier/logo/logo_dowatx.png\" alt='Saffier'></a>\n</p>\n\n<p align=\"center\">\n    <em>\ud83d\ude80 The only Async ORM you need. \ud83d\ude80</em>\n</p>\n\n<p align=\"center\">\n<a href=\"https://github.com/tarsil/saffier/workflows/Test%20Suite/badge.svg?event=push&branch=main\" target=\"_blank\">\n    <img src=\"https://github.com/tarsil/saffier/workflows/Test%20Suite/badge.svg?event=push&branch=main\" alt=\"Test Suite\">\n</a>\n\n<a href=\"https://pypi.org/project/saffier\" target=\"_blank\">\n    <img src=\"https://img.shields.io/pypi/v/saffier?color=%2334D058&label=pypi%20package\" alt=\"Package version\">\n</a>\n\n<a href=\"https://pypi.org/project/saffier\" target=\"_blank\">\n    <img src=\"https://img.shields.io/pypi/pyversions/saffier.svg?color=%2334D058\" alt=\"Supported Python versions\">\n</a>\n</p>\n\n---\n\n**Documentation**: [https://saffier.tarsild.io](https://saffier.tarsild.io) \ud83d\udcda\n\n**Source Code**: [https://github.com/tarsil/saffier](https://github.com/tarsil/saffier)\n\n---\n\n## Motivation\n\nAlmost every project, in one way or another uses one (or many) databases. An ORM is simply an mapping\nof the top of an existing database. ORM extends for Object Relational Mapping and bridges object-oriented\nprograms and relational databases.\n\nTwo of the most well known ORMs are from Django and SQLAlchemy. Both have their own strengths and\nweaknesses and specific use cases.\n\nThis ORM is built on the top of SQLAlchemy core and aims to simplify the way the setup and queries\nare done into a more common and familiar interface.\n\n## Before continuing\n\nIf you are looking for something more **Pyadntic** oriented where you can take literally advantage\nof everything that Pydantic can offer, then instead of continuing with Saffier, have a look at\nits ***data ORM brother***, [Edgy](https://edgy.tarsild.io).\n\n**Edgy** its extremely powerful as well with a key difference that its **100% Pydantic** which means\nyou can leverage the technology if you already familiar with it.\n\nNo worries, it is not completely different from Saffier, in fact, it was designed with the same principles and what it changes for you\nare essentially the ***imports***.\n\n### Thinking of moving to Edgy?\n\nIf you are considering of moving to Edgy but you don't want to be bothered about learning a new\ntool and afraid of breaking changes, then fear not!\n\nEdgy was designed to also make your migration feel seemless, which means that essentially you would\nonly need to install it and change the imports in your project from `saffier` to `edgy` and it should\nwork automatically for you.\n\nEven the documentation structure its almost the same, intentionally, so what you already know with\nSaffier, you will know with **Edgy**.\n\n**This discards any custom code done by you, of course.**\n\n## Why this ORM\n\nWhen investigating for a project different types of ORMs and compared them to each other, for a lot\nof use cases, SQLAlchemyalways took the win but had an issue, the async support (which now there\nare a few solutions). While doing the research I came across [Encode ORM](https://www.encode.io/orm/).\n\nThe team is the same behind of Databases, Django Rest Framework, Starlette,\nhttpx and a lot more tools used by millions.\n\nThere was one issue though, although ORM was doing a great familiar interface with SQLAlchemy and\nproviding the async solution needed, it was, by the time of this writing, incomplete and they\neven stated that in the documentation and that is how **Saffier** was born.\n\nSaffier uses some of the same concepts of ORM from Encode but rewritten in **Pydantic** but not all.\n\n## Saffier\n\nSaffier is some sort of a fork from [Encode ORM](https://www.encode.io/orm/) but rewritten at its\ncore and with a complete set of tools with a familiar interface to work with.\nIf you are familiar with Django, then you came for a treat \ud83d\ude04.\n\nSaffier leverages the power of **Pydantic** for its fields while offering a friendly, familiar and\neasy to use interface.\n\nThis ORM was designed to be flexible and compatible with pretty much every ASGI framework, like\n[Esmerald](https://esmerald.dymmond.com), Starlette, FastAPI, Sanic, Quart... With simple pluggable\ndesign thanks to its origins.\n\n### Special notes\n\nSaffier couldn't exist without [Encode ORM](https://www.encode.io/orm/) and the continous work\ndone by the amazing team behind it. For that reason, thank you!\n\n## Features\n\nWhile adopting a familiar interface, it offers some cool and powerful features on the top of\nSQLAlchemy core.\n\n### Key features\n\n* **Model inheritance** - For those cases where you don't want to repeat yourself while maintaining\nintregity of the models.\n* **Abstract classes** - That's right! Sometimes you simply want a model that holds common fields\nthat doesn't need to created as a table in the database.\n* **Meta classes** - If you are familiar with Django, this is not new to you and Saffier offers this\nin the same fashion.\n* **Managers** - Versatility at its core, you can have separate managers for your models to optimise\nspecific queries and querysets at ease.\n* **Filters** - Filter by any field you want and need.\n* **Model operators** - Classic operations such as `update`, `get`, `get_or_none`, `bulk_create`,\n`bulk_update` and a lot more.\n* **Relationships made it easy** - Support for `OneToOne` and `ForeignKey` in the same Django style.\n* **Constraints** - Unique constraints through meta fields.\n* **Native test client** - We all know how hard it can be to setup that client for those tests you\nneed so we give you already one.\n* **Multi-tenancy** - Saffier supports multi-tenancy and even offers a possible solution to be used\nout of the box if you don't want to waste time.\n\nAnd a lot more you can do here.\n\n## Migrations\n\nSince **Saffier**, like [Encode ORM](https://www.encode.io/orm/), is built on the top of\n[SQLAlchemy core](https://docs.sqlalchemy.org/en/20/core/), it brings its own native migration\nsystem running on the top of [Alembic](https://alembic.sqlalchemy.org/en/latest/) but making it a\nlot easier to use and more pleasant for you.\n\nHave a look at the [migrations](https://saffier.tarsild.io/migrations.md) for more details.\n\n## Installation\n\nTo install Saffier, simply run:\n\n```shell\n$ pip install saffier\n```\n\nYou can pickup your favourite database driver by yourself or you can run:\n\n**Postgres**\n\n```shell\n$ pip install saffier[postgres]\n```\n\n**MySQL/MariaDB**\n\n```shell\n$ pip install saffier[mysql]\n```\n\n**SQLite**\n\n```shell\n$ pip install saffier[sqlite]\n```\n\n## Quick Start\n\nThe following is an example how to start with **Saffier** and more details and examples can be\nfound throughout the documentation.\n\n**Use** `ipython` **to run the following from the console, since it supports** `await`.\n\n```python\nimport saffier\nfrom saffier import Database, Registry\n\ndatabase = Database(\"sqlite:///db.sqlite\")\nmodels = Registry(database=database)\n\n\nclass User(saffier.Model):\n    \"\"\"\n    The User model to be created in the database as a table\n    If no name is provided the in Meta class, it will generate\n    a \"users\" table for you.\n    \"\"\"\n\n    id = saffier.IntegerField(primary_key=True)\n    is_active = saffier.BooleanField(default=False)\n\n    class Meta:\n        registry = models\n\n\n# Create the db and tables\n# Don't use this in production! Use Alembic or any tool to manage\n# The migrations for you\nawait models.create_all()\n\nawait User.query.create(is_active=False)\n\nuser = await User.query.get(id=1)\nprint(user)\n# User(id=1)\n\n```\n\nAs stated in the example, if no `tablename` is provided in the `Meta` class, Saffier automatically\ngenerates the name of the table for you by pluralising the class name.\n\n## Connect your application\n\nDo you want to have more complex structures and connect to your favourite framework? Have a look\nat [connections](https:/saffier.tarsild.io/connection.md) to understand how to do it properly.\n\n**Exciting!**\n\nIn the documentation we go deeper in explanations and examples, this was just to warm up. \ud83d\ude01\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "The only python ORM you will ever need.",
    "version": "1.3.7",
    "project_urls": {
        "Changelog": "https://saffier.tarsild.io/release-notes/",
        "Documentation": "https://saffier.tarsild.io/",
        "Funding": "https://github.com/sponsors/tarsil",
        "Homepage": "https://github.com/tarsil/saffier",
        "Source": "https://github.com/tarsil/saffier"
    },
    "split_keywords": [
        "api",
        "asgi",
        "fastapi",
        "framework",
        "http",
        "machine learning",
        "ml",
        "openapi",
        "pydantic",
        "rest",
        "starlette",
        "websocket"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8f8f435ad18ac1c77f9e8d9cc0e785a12da6ff25562cc095aaf2b4e4ca5bb279",
                "md5": "67b7ca6733f2e5d824e3ae9b11b6b62e",
                "sha256": "e88af4cd7ffd19c7b8e5e9418ac2ee01a3bc4698aa6a6286877c81c70b32b56e"
            },
            "downloads": -1,
            "filename": "saffier-1.3.7-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "67b7ca6733f2e5d824e3ae9b11b6b62e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 108346,
            "upload_time": "2024-03-08T11:38:55",
            "upload_time_iso_8601": "2024-03-08T11:38:55.948609Z",
            "url": "https://files.pythonhosted.org/packages/8f/8f/435ad18ac1c77f9e8d9cc0e785a12da6ff25562cc095aaf2b4e4ca5bb279/saffier-1.3.7-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "898927eb76c9e4bf8dede12a2044edc00c958a9f2d4fc89b459cd55d20af244d",
                "md5": "76f843b7114fed03b40a2f2ea55b3863",
                "sha256": "7178a2b6bff126daf96617dab9d70be5bffcb42fdf287d0807f9aa994b4c2ac6"
            },
            "downloads": -1,
            "filename": "saffier-1.3.7.tar.gz",
            "has_sig": false,
            "md5_digest": "76f843b7114fed03b40a2f2ea55b3863",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 72063,
            "upload_time": "2024-03-08T11:38:58",
            "upload_time_iso_8601": "2024-03-08T11:38:58.137123Z",
            "url": "https://files.pythonhosted.org/packages/89/89/27eb76c9e4bf8dede12a2044edc00c958a9f2d4fc89b459cd55d20af244d/saffier-1.3.7.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-03-08 11:38:58",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "sponsors",
    "github_project": "tarsil",
    "github_not_found": true,
    "lcname": "saffier"
}
        
Elapsed time: 0.24121s