# [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"
}