fastapi-class


Namefastapi-class JSON
Version 3.6.0 PyPI version JSON
download
home_pageNone
SummarySimplifies class-based views for more organized and maintainable code in FastAPI.
upload_time2024-04-20 16:48:09
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords fastapi mvc class-based class-based-views pydantic
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ![Class](https://user-images.githubusercontent.com/52716203/137606695-f110f129-08b1-45f3-a445-962c1f28378c.png)

<p align="center">
    <em>Classes and Decorators to use FastAPI with Class based routing</em>
</p>

<p align="center">
<a href="https://github.com/yezz123/fastapi-class/actions/workflows/ci.yml" target="_blank">
    <img src="https://github.com/yezz123/fastapi-class/actions/workflows/ci.yml/badge.svg" alt="Continuous Integration">
</a>
<a href="https://codecov.io/gh/yezz123/fastapi-class">
    <img src="https://codecov.io/gh/yezz123/fastapi-class/branch/main/graph/badge.svg"/>
</a>
<a href="https://pypi.org/project/fastapi-class" target="_blank">
    <img src="https://img.shields.io/pypi/v/fastapi-class?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi-class" target="_blank">
    <img src="https://img.shields.io/pypi/pyversions/fastapi-class.svg?color=%2334D058" alt="Supported Python versions">
</a>
<a href="https://pepy.tech/project/fastapi_class" target="_blank">
    <img src="https://static.pepy.tech/badge/fastapi_class" alt="Test">
</a>
</p>

---

**Source Code**: <https://github.com/yezz123/fastapi-class>

**Install the project**: `pip install fastapi-class`

---

As you create more complex FastAPI applications, you may find yourself frequently repeating the same dependencies in multiple related endpoints.

A common question people have as they become more comfortable with FastAPI is how they can reduce the number of times they have to copy/paste the same dependency into related routes.

`fastapi_class` provides a `class-based view` decorator `@View` to help reduce the amount of boilerplate necessary when developing related routes.

> Highly inspired by [Fastapi-utils](https://fastapi-utils.davidmontague.xyz/user-guide/class-based-views/), Thanks to [@dmontagu](https://github.com/dmontagu) for the great work.

- Example:

```python
from fastapi import FastAPI, Query
from pydantic import BaseModel
from fastapi_class import View

app = FastAPI()

class ItemModel(BaseModel):
    id: int
    name: str
    description: str = None

@View(app)
class ItemView:
    async def post(self, item: ItemModel):
        return item

    async def get(self, item_id: int = Query(..., gt=0)):
        return {"item_id": item_id}

```

### Response model 📦

`Exception` in list need to be either function that return `fastapi.HTTPException` itself. In case of a function it is required to have all of it's arguments to be `optional`.

```py
from fastapi import FastAPI, HTTPException, status
from fastapi.responses import PlainTextResponse
from pydantic import BaseModel

from fastapi_class import View

app = FastAPI()

NOT_AUTHORIZED = HTTPException(401, "Not authorized.")
NOT_ALLOWED = HTTPException(405, "Method not allowed.")
NOT_FOUND = lambda item_id="item_id": HTTPException(404, f"Item with {item_id} not found.")

class ItemResponse(BaseModel):
    field: str | None = None

@View(app)
class MyView:
    exceptions = {
        "__all__": [NOT_AUTHORIZED],
        "put": [NOT_ALLOWED, NOT_FOUND]
    }

    RESPONSE_MODEL = {
        "put": ItemResponse
    }

    RESPONSE_CLASS = {
        "delete": PlainTextResponse
    }

    async def get(self):
        ...

    async def put(self):
        ...

    async def delete(self):
        ...
```

### Customized Endpoints

```py
from fastapi import FastAPI, HTTPException
from fastapi.responses import PlainTextResponse
from pydantic import BaseModel

from fastapi_class import View, endpoint

app = FastAPI()

NOT_AUTHORIZED = HTTPException(401, "Not authorized.")
NOT_ALLOWED = HTTPException(405, "Method not allowed.")
NOT_FOUND = lambda item_id="item_id": HTTPException(404, f"Item with {item_id} not found.")
EXCEPTION = HTTPException(400, "Example.")

class UserResponse(BaseModel):
    field: str | None = None

@View(app)
class MyView:
    exceptions = {
        "__all__": [NOT_AUTHORIZED],
        "put": [NOT_ALLOWED, NOT_FOUND],
        "edit": [EXCEPTION]
    }

    RESPONSE_MODEL = {
        "put": UserResponse,
        "edit": UserResponse
    }

    RESPONSE_CLASS = {
        "delete": PlainTextResponse
    }

    async def get(self):
        ...

    async def put(self):
        ...

    async def delete(self):
        ...

    @endpoint(("PUT"), path="edit")
    async def edit(self):
        ...
```

**Note:** The `edit()` endpoint is decorated with the `@endpoint(("PUT",), path="edit")` decorator, which specifies that this endpoint should handle `PUT` requests to the `/edit` path,
using `@endpoint("PUT", path="edit")` has the same effect

## Development 🚧

### Setup environment 📦

You should create a virtual environment and activate it:

```bash
python -m venv venv/
```

```bash
source venv/bin/activate
```

And then install the development dependencies:

__Note:__ You should have `uv` installed, if not you can install it with:

```bash
pip install uv
```

Then you can install the dependencies with:

```bash
# Install dependencies
uv pip install -r requirements/all.txt
```

### Run tests 🌝

You can run all the tests with:

```bash
bash scripts/test.sh
```

### Format the code 🍂

Execute the following command to apply `pre-commit` formatting:

```bash
bash scripts/format.sh
```

Execute the following command to apply `mypy` type checking:

```bash
bash scripts/lint.sh
```

## License

This project is licensed under the terms of the MIT license.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "fastapi-class",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "FastAPI, MVC, class-based, class-based-views, pydantic",
    "author": null,
    "author_email": "Yasser Tahiri <hello@yezz.me>",
    "download_url": "https://files.pythonhosted.org/packages/7b/38/15dd1f1aed9b78eb5e5ebe117e4dd8900b4b6f50a1aef5d053c3003c5eaf/fastapi_class-3.6.0.tar.gz",
    "platform": null,
    "description": "![Class](https://user-images.githubusercontent.com/52716203/137606695-f110f129-08b1-45f3-a445-962c1f28378c.png)\n\n<p align=\"center\">\n    <em>Classes and Decorators to use FastAPI with Class based routing</em>\n</p>\n\n<p align=\"center\">\n<a href=\"https://github.com/yezz123/fastapi-class/actions/workflows/ci.yml\" target=\"_blank\">\n    <img src=\"https://github.com/yezz123/fastapi-class/actions/workflows/ci.yml/badge.svg\" alt=\"Continuous Integration\">\n</a>\n<a href=\"https://codecov.io/gh/yezz123/fastapi-class\">\n    <img src=\"https://codecov.io/gh/yezz123/fastapi-class/branch/main/graph/badge.svg\"/>\n</a>\n<a href=\"https://pypi.org/project/fastapi-class\" target=\"_blank\">\n    <img src=\"https://img.shields.io/pypi/v/fastapi-class?color=%2334D058&label=pypi%20package\" alt=\"Package version\">\n</a>\n<a href=\"https://pypi.org/project/fastapi-class\" target=\"_blank\">\n    <img src=\"https://img.shields.io/pypi/pyversions/fastapi-class.svg?color=%2334D058\" alt=\"Supported Python versions\">\n</a>\n<a href=\"https://pepy.tech/project/fastapi_class\" target=\"_blank\">\n    <img src=\"https://static.pepy.tech/badge/fastapi_class\" alt=\"Test\">\n</a>\n</p>\n\n---\n\n**Source Code**: <https://github.com/yezz123/fastapi-class>\n\n**Install the project**: `pip install fastapi-class`\n\n---\n\nAs you create more complex FastAPI applications, you may find yourself frequently repeating the same dependencies in multiple related endpoints.\n\nA common question people have as they become more comfortable with FastAPI is how they can reduce the number of times they have to copy/paste the same dependency into related routes.\n\n`fastapi_class` provides a `class-based view` decorator `@View` to help reduce the amount of boilerplate necessary when developing related routes.\n\n> Highly inspired by [Fastapi-utils](https://fastapi-utils.davidmontague.xyz/user-guide/class-based-views/), Thanks to [@dmontagu](https://github.com/dmontagu) for the great work.\n\n- Example:\n\n```python\nfrom fastapi import FastAPI, Query\nfrom pydantic import BaseModel\nfrom fastapi_class import View\n\napp = FastAPI()\n\nclass ItemModel(BaseModel):\n    id: int\n    name: str\n    description: str = None\n\n@View(app)\nclass ItemView:\n    async def post(self, item: ItemModel):\n        return item\n\n    async def get(self, item_id: int = Query(..., gt=0)):\n        return {\"item_id\": item_id}\n\n```\n\n### Response model \ud83d\udce6\n\n`Exception` in list need to be either function that return `fastapi.HTTPException` itself. In case of a function it is required to have all of it's arguments to be `optional`.\n\n```py\nfrom fastapi import FastAPI, HTTPException, status\nfrom fastapi.responses import PlainTextResponse\nfrom pydantic import BaseModel\n\nfrom fastapi_class import View\n\napp = FastAPI()\n\nNOT_AUTHORIZED = HTTPException(401, \"Not authorized.\")\nNOT_ALLOWED = HTTPException(405, \"Method not allowed.\")\nNOT_FOUND = lambda item_id=\"item_id\": HTTPException(404, f\"Item with {item_id} not found.\")\n\nclass ItemResponse(BaseModel):\n    field: str | None = None\n\n@View(app)\nclass MyView:\n    exceptions = {\n        \"__all__\": [NOT_AUTHORIZED],\n        \"put\": [NOT_ALLOWED, NOT_FOUND]\n    }\n\n    RESPONSE_MODEL = {\n        \"put\": ItemResponse\n    }\n\n    RESPONSE_CLASS = {\n        \"delete\": PlainTextResponse\n    }\n\n    async def get(self):\n        ...\n\n    async def put(self):\n        ...\n\n    async def delete(self):\n        ...\n```\n\n### Customized Endpoints\n\n```py\nfrom fastapi import FastAPI, HTTPException\nfrom fastapi.responses import PlainTextResponse\nfrom pydantic import BaseModel\n\nfrom fastapi_class import View, endpoint\n\napp = FastAPI()\n\nNOT_AUTHORIZED = HTTPException(401, \"Not authorized.\")\nNOT_ALLOWED = HTTPException(405, \"Method not allowed.\")\nNOT_FOUND = lambda item_id=\"item_id\": HTTPException(404, f\"Item with {item_id} not found.\")\nEXCEPTION = HTTPException(400, \"Example.\")\n\nclass UserResponse(BaseModel):\n    field: str | None = None\n\n@View(app)\nclass MyView:\n    exceptions = {\n        \"__all__\": [NOT_AUTHORIZED],\n        \"put\": [NOT_ALLOWED, NOT_FOUND],\n        \"edit\": [EXCEPTION]\n    }\n\n    RESPONSE_MODEL = {\n        \"put\": UserResponse,\n        \"edit\": UserResponse\n    }\n\n    RESPONSE_CLASS = {\n        \"delete\": PlainTextResponse\n    }\n\n    async def get(self):\n        ...\n\n    async def put(self):\n        ...\n\n    async def delete(self):\n        ...\n\n    @endpoint((\"PUT\"), path=\"edit\")\n    async def edit(self):\n        ...\n```\n\n**Note:** The `edit()` endpoint is decorated with the `@endpoint((\"PUT\",), path=\"edit\")` decorator, which specifies that this endpoint should handle `PUT` requests to the `/edit` path,\nusing `@endpoint(\"PUT\", path=\"edit\")` has the same effect\n\n## Development \ud83d\udea7\n\n### Setup environment \ud83d\udce6\n\nYou should create a virtual environment and activate it:\n\n```bash\npython -m venv venv/\n```\n\n```bash\nsource venv/bin/activate\n```\n\nAnd then install the development dependencies:\n\n__Note:__ You should have `uv` installed, if not you can install it with:\n\n```bash\npip install uv\n```\n\nThen you can install the dependencies with:\n\n```bash\n# Install dependencies\nuv pip install -r requirements/all.txt\n```\n\n### Run tests \ud83c\udf1d\n\nYou can run all the tests with:\n\n```bash\nbash scripts/test.sh\n```\n\n### Format the code \ud83c\udf42\n\nExecute the following command to apply `pre-commit` formatting:\n\n```bash\nbash scripts/format.sh\n```\n\nExecute the following command to apply `mypy` type checking:\n\n```bash\nbash scripts/lint.sh\n```\n\n## License\n\nThis project is licensed under the terms of the MIT license.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Simplifies class-based views for more organized and maintainable code in FastAPI.",
    "version": "3.6.0",
    "project_urls": {
        "Funding": "https://github.com/sponsors/yezz123",
        "Homepage": "https://github.com/yezz123/fastapi-class"
    },
    "split_keywords": [
        "fastapi",
        " mvc",
        " class-based",
        " class-based-views",
        " pydantic"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "94798bfb7e8087053e2eecb41a1cf8e93d6cb87ee634c48ca9eec0879c5e72f7",
                "md5": "9a67efaf52e8eddd8d5148f0b87709fc",
                "sha256": "7349376e9c88534ca8a4b8bec5d9af57e2985d0552595b955536ced904d8a6cc"
            },
            "downloads": -1,
            "filename": "fastapi_class-3.6.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "9a67efaf52e8eddd8d5148f0b87709fc",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 9472,
            "upload_time": "2024-04-20T16:48:08",
            "upload_time_iso_8601": "2024-04-20T16:48:08.376712Z",
            "url": "https://files.pythonhosted.org/packages/94/79/8bfb7e8087053e2eecb41a1cf8e93d6cb87ee634c48ca9eec0879c5e72f7/fastapi_class-3.6.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7b3815dd1f1aed9b78eb5e5ebe117e4dd8900b4b6f50a1aef5d053c3003c5eaf",
                "md5": "a553e3903f64487290386157961cc722",
                "sha256": "4e6e1f949b67a88958f1a30088d4359bd816ee338df89e898877346cb7a49a22"
            },
            "downloads": -1,
            "filename": "fastapi_class-3.6.0.tar.gz",
            "has_sig": false,
            "md5_digest": "a553e3903f64487290386157961cc722",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 13458,
            "upload_time": "2024-04-20T16:48:09",
            "upload_time_iso_8601": "2024-04-20T16:48:09.929614Z",
            "url": "https://files.pythonhosted.org/packages/7b/38/15dd1f1aed9b78eb5e5ebe117e4dd8900b4b6f50a1aef5d053c3003c5eaf/fastapi_class-3.6.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-20 16:48:09",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "sponsors",
    "github_project": "yezz123",
    "github_not_found": true,
    "lcname": "fastapi-class"
}
        
Elapsed time: 0.22829s