fastgql


Namefastgql JSON
Version 0.21.2 PyPI version JSON
download
home_pagehttps://github.com/jerber/fastgql
SummaryThe easiest, fastest python GraphQL framework.
upload_time2024-05-13 21:37:10
maintainerNone
docs_urlNone
authorJeremy Berman
requires_python<4.0,>=3.10
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # [Presentation](https://youtu.be/r--YN_6a76g?si=aWdBFagVPJfWDD6K&t=2155)
[![](docs/docs/images/fastgql%20shot.jpg)](https://youtu.be/r--YN_6a76g?si=aWdBFagVPJfWDD6K&t=2155)
# [Documentation](https://jerber.github.io/fastgql)
# FastGQL

**FastGQL** is a python GraphQL library that uses Pydantic models to build GraphQL types. Think FastAPI for GraphQL.

```py
from fastapi import FastAPI
from fastgql import GQL, build_router

class User(GQL):
    name: str
    age: int

class Query(GQL):
    def user_by_name(self, name: str) -> User:
        return User(name=name, age=27)

router = build_router(query_models=[Query])

app = FastAPI()

app.include_router(router, prefix="/graphql")
```
I built **FastGQL** because I wanted a GraphQL framework that

1. let me use `pydantic.BaseModel` objects to define my schema
2. let me build dynamic database queries based on incoming requests

We are now using **FastGQL** in production and have experienced a massive (10x) speedup in average response times because of 2).

You can find out more about how we build dynamic database queries in the Advanced Tutorial section of the docs.

## Installation

<div class="termy">

```console
$ pip install fastgql
---> 100%
Successfully installed fastgql
```

</div>

## Example

All you need to do is create objects that inherit from `fastgql.GQL`, which is a simple subclass of `pydantic.BaseModel`. For this example, I am creating a mock schema based on movies. For the functions, you'd usually use a database but I hardcoded the data for this example.

This code generates a GraphQL schema, reading the object fields and functions. Functions can be sync or async.

### Code it

- Create a file `main.py` with:

```py title="main.py"
from uuid import UUID, uuid4
from fastapi import FastAPI
from fastgql import GQL, build_router

class Account(GQL):  # (4)!
    id: UUID
    username: str

    def watchlist(self) -> list["Movie"]:  # (1)!
        # Usually you'd use a database to get the user's watchlist. For this example, it is hardcoded.
        return [
            Movie(id=uuid4(), title="Barbie", release_year=2023),
            Movie(id=uuid4(), title="Oppenheimer", release_year=2023),
        ]

    def _secret_function(self) -> str:  # (2)!
        return "this is not exposed!"

class Person(GQL):
    id: UUID
    name: str

    def filmography(self) -> list["Movie"]:
        return [
            Movie(id=uuid4(), title="Barbie", release_year=2023),
            Movie(id=uuid4(), title="Wolf of Wallstreet", release_year=2013),
        ]

class Movie(GQL):
    id: UUID
    title: str
    release_year: int

    def actors(self) -> list["Person"]:
        return [
            Person(id=uuid4(), name="Margot Robbie"),
            Person(id=uuid4(), name="Ryan Gosling"),
        ]

class Query(GQL):
    def account_by_username(self, username: str) -> Account:  # (5)!
        # Usually you'd use a database to get this account. For this example, it is hardcoded.
        return Account(id=uuid4(), username=username)

router = build_router(query_models=[Query])

app = FastAPI()  # (3)!

app.include_router(router, prefix="/graphql")
```

1. Usually this would be a database call. There is an advanced tutorial showing this.
2. Functions that start with `_` are not included in the GraphQL schema.
3. This is just a normal FastAPI app. `fastgql.build_router` returns a router that can be included on any FastAPI app.
4. These objects are subclasses of `pydantic.BaseModel`, so anything you'd want to do with a `BaseModel` you can do with these. You'll see how this comes in handy in future tutorials.
5. All of these functions can be sync or async. In a future tutorial I'll use an async database call to get data.

### Run it

Run the server with:

<div class="termy">

```console
$ uvicorn main:app --reload

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [28720]
INFO:     Started server process [28722]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
```

</div>

<details markdown="1">
<summary>(Taken from FastAPI docs) About the command <code>uvicorn main:app --reload</code>...</summary>

The command `uvicorn main:app` refers to:

- `main`: the file `main.py` (the Python "module").
- `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
- `--reload`: make the server restart after code changes. Only do this for development.

</details>

### Check it

Open your browser at <a href="http://127.0.0.1:8000/graphql" class="external-link" target="_blank">http://127.0.0.1:8000/graphql</a>.

You will see a GraphiQL UI. This is your homebase for creating GraphQL queries and checking the schema.

![](docs/docs/images/graphiql.png)

You can see the schema, build queries, and access query history from the icons in the top left respectivly. Here is an example query:

![](docs/docs/images/account_by_username_query.png)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jerber/fastgql",
    "name": "fastgql",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.10",
    "maintainer_email": null,
    "keywords": null,
    "author": "Jeremy Berman",
    "author_email": "jerber@sas.upenn.edu",
    "download_url": "https://files.pythonhosted.org/packages/25/49/d0523288eab45c6ea561d26d561934ac63e1bf2906ec89ecf2c1243ffc79/fastgql-0.21.2.tar.gz",
    "platform": null,
    "description": "# [Presentation](https://youtu.be/r--YN_6a76g?si=aWdBFagVPJfWDD6K&t=2155)\n[![](docs/docs/images/fastgql%20shot.jpg)](https://youtu.be/r--YN_6a76g?si=aWdBFagVPJfWDD6K&t=2155)\n# [Documentation](https://jerber.github.io/fastgql)\n# FastGQL\n\n**FastGQL** is a python GraphQL library that uses Pydantic models to build GraphQL types. Think FastAPI for GraphQL.\n\n```py\nfrom fastapi import FastAPI\nfrom fastgql import GQL, build_router\n\nclass User(GQL):\n    name: str\n    age: int\n\nclass Query(GQL):\n    def user_by_name(self, name: str) -> User:\n        return User(name=name, age=27)\n\nrouter = build_router(query_models=[Query])\n\napp = FastAPI()\n\napp.include_router(router, prefix=\"/graphql\")\n```\nI built **FastGQL** because I wanted a GraphQL framework that\n\n1. let me use `pydantic.BaseModel` objects to define my schema\n2. let me build dynamic database queries based on incoming requests\n\nWe are now using **FastGQL** in production and have experienced a massive (10x) speedup in average response times because of 2).\n\nYou can find out more about how we build dynamic database queries in the Advanced Tutorial section of the docs.\n\n## Installation\n\n<div class=\"termy\">\n\n```console\n$ pip install fastgql\n---> 100%\nSuccessfully installed fastgql\n```\n\n</div>\n\n## Example\n\nAll you need to do is create objects that inherit from `fastgql.GQL`, which is a simple subclass of `pydantic.BaseModel`. For this example, I am creating a mock schema based on movies. For the functions, you'd usually use a database but I hardcoded the data for this example.\n\nThis code generates a GraphQL schema, reading the object fields and functions. Functions can be sync or async.\n\n### Code it\n\n- Create a file `main.py` with:\n\n```py title=\"main.py\"\nfrom uuid import UUID, uuid4\nfrom fastapi import FastAPI\nfrom fastgql import GQL, build_router\n\nclass Account(GQL):  # (4)!\n    id: UUID\n    username: str\n\n    def watchlist(self) -> list[\"Movie\"]:  # (1)!\n        # Usually you'd use a database to get the user's watchlist. For this example, it is hardcoded.\n        return [\n            Movie(id=uuid4(), title=\"Barbie\", release_year=2023),\n            Movie(id=uuid4(), title=\"Oppenheimer\", release_year=2023),\n        ]\n\n    def _secret_function(self) -> str:  # (2)!\n        return \"this is not exposed!\"\n\nclass Person(GQL):\n    id: UUID\n    name: str\n\n    def filmography(self) -> list[\"Movie\"]:\n        return [\n            Movie(id=uuid4(), title=\"Barbie\", release_year=2023),\n            Movie(id=uuid4(), title=\"Wolf of Wallstreet\", release_year=2013),\n        ]\n\nclass Movie(GQL):\n    id: UUID\n    title: str\n    release_year: int\n\n    def actors(self) -> list[\"Person\"]:\n        return [\n            Person(id=uuid4(), name=\"Margot Robbie\"),\n            Person(id=uuid4(), name=\"Ryan Gosling\"),\n        ]\n\nclass Query(GQL):\n    def account_by_username(self, username: str) -> Account:  # (5)!\n        # Usually you'd use a database to get this account. For this example, it is hardcoded.\n        return Account(id=uuid4(), username=username)\n\nrouter = build_router(query_models=[Query])\n\napp = FastAPI()  # (3)!\n\napp.include_router(router, prefix=\"/graphql\")\n```\n\n1. Usually this would be a database call. There is an advanced tutorial showing this.\n2. Functions that start with `_` are not included in the GraphQL schema.\n3. This is just a normal FastAPI app. `fastgql.build_router` returns a router that can be included on any FastAPI app.\n4. These objects are subclasses of `pydantic.BaseModel`, so anything you'd want to do with a `BaseModel` you can do with these. You'll see how this comes in handy in future tutorials.\n5. All of these functions can be sync or async. In a future tutorial I'll use an async database call to get data.\n\n### Run it\n\nRun the server with:\n\n<div class=\"termy\">\n\n```console\n$ uvicorn main:app --reload\n\nINFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)\nINFO:     Started reloader process [28720]\nINFO:     Started server process [28722]\nINFO:     Waiting for application startup.\nINFO:     Application startup complete.\n```\n\n</div>\n\n<details markdown=\"1\">\n<summary>(Taken from FastAPI docs) About the command <code>uvicorn main:app --reload</code>...</summary>\n\nThe command `uvicorn main:app` refers to:\n\n- `main`: the file `main.py` (the Python \"module\").\n- `app`: the object created inside of `main.py` with the line `app = FastAPI()`.\n- `--reload`: make the server restart after code changes. Only do this for development.\n\n</details>\n\n### Check it\n\nOpen your browser at <a href=\"http://127.0.0.1:8000/graphql\" class=\"external-link\" target=\"_blank\">http://127.0.0.1:8000/graphql</a>.\n\nYou will see a GraphiQL UI. This is your homebase for creating GraphQL queries and checking the schema.\n\n![](docs/docs/images/graphiql.png)\n\nYou can see the schema, build queries, and access query history from the icons in the top left respectivly. Here is an example query:\n\n![](docs/docs/images/account_by_username_query.png)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "The easiest, fastest python GraphQL framework.",
    "version": "0.21.2",
    "project_urls": {
        "Documentation": "https://jerber.github.io/fastgql/",
        "Homepage": "https://github.com/jerber/fastgql",
        "Repository": "https://github.com/jerber/fastgql"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c99a73ebc894b24fd11b13e2ce58952215b1d57d6eb549fbea508b0407ec4ac8",
                "md5": "41a58a0ece91aa436df0a1106b21f2d2",
                "sha256": "29387010a979e0c62a0647d5f8b2d8d2bb3000c5a871419a6604f3277eb9b7b1"
            },
            "downloads": -1,
            "filename": "fastgql-0.21.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "41a58a0ece91aa436df0a1106b21f2d2",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.10",
            "size": 40120,
            "upload_time": "2024-05-13T21:37:08",
            "upload_time_iso_8601": "2024-05-13T21:37:08.359337Z",
            "url": "https://files.pythonhosted.org/packages/c9/9a/73ebc894b24fd11b13e2ce58952215b1d57d6eb549fbea508b0407ec4ac8/fastgql-0.21.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2549d0523288eab45c6ea561d26d561934ac63e1bf2906ec89ecf2c1243ffc79",
                "md5": "5469eb6e6534ee67ddccaa40061b717e",
                "sha256": "ba849764e45f378c9b703d6226436a82931af9d3361bd491e003c29782a61016"
            },
            "downloads": -1,
            "filename": "fastgql-0.21.2.tar.gz",
            "has_sig": false,
            "md5_digest": "5469eb6e6534ee67ddccaa40061b717e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.10",
            "size": 32582,
            "upload_time": "2024-05-13T21:37:10",
            "upload_time_iso_8601": "2024-05-13T21:37:10.132272Z",
            "url": "https://files.pythonhosted.org/packages/25/49/d0523288eab45c6ea561d26d561934ac63e1bf2906ec89ecf2c1243ffc79/fastgql-0.21.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-05-13 21:37:10",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jerber",
    "github_project": "fastgql",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "fastgql"
}
        
Elapsed time: 0.31510s