Skip to content

Commit 3930dbc

Browse files
committed
FastAPI Starter Base.
0 parents  commit 3930dbc

14 files changed

+1261
-0
lines changed

.gitignore

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
**/.DS_Store
30+
**/__pycache__
31+
bin
32+
33+
# PyInstaller
34+
# Usually these files are written by a python script from a template
35+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
36+
*.manifest
37+
*.spec
38+
39+
# Installer logs
40+
pip-log.txt
41+
pip-delete-this-directory.txt
42+
43+
# Unit test / coverage reports
44+
htmlcov/
45+
.tox/
46+
.nox/
47+
.coverage
48+
.coverage.*
49+
.cache
50+
nosetests.xml
51+
coverage.xml
52+
*.cover
53+
*.py,cover
54+
.hypothesis/
55+
.pytest_cache/
56+
57+
# Translations
58+
*.mo
59+
*.pot
60+
61+
# Scrapy stuff:
62+
.scrapy
63+
64+
# Sphinx documentation
65+
docs/_build/
66+
67+
# PyBuilder
68+
target/
69+
70+
# Jupyter Notebook
71+
.ipynb_checkpoints
72+
73+
# IPython
74+
profile_default/
75+
ipython_config.py
76+
77+
# pyenv
78+
.python-version
79+
80+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
81+
__pypackages__/
82+
83+
84+
# SageMath parsed files
85+
*.sage.py
86+
87+
# Environments
88+
.env
89+
.venv
90+
env/
91+
venv/
92+
ENV/
93+
env.bak/
94+
venv.bak/
95+
.envrc
96+
97+
# Spyder project settings
98+
.spyderproject
99+
.spyproject
100+
101+
# Rope project settings
102+
.ropeproject
103+
104+
# mkdocs documentation
105+
/site
106+
107+
# mypy
108+
.mypy_cache/
109+
.dmypy.json
110+
dmypy.json
111+
112+
# Pyre type checker
113+
.pyre/
114+
115+
# Editor stuff
116+
.idea
117+
118+
backend/bin

Dockerfile.web

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
FROM python:3.9
2+
3+
RUN pip install fastapi uvicorn
4+
5+
# Install Environment Dependencies (Image Base)
6+
RUN pip install fastapi uvicorn poetry wheel virtualenv
7+
8+
EXPOSE 8000
9+
EXPOSE 8001
10+
11+
# set working directory
12+
WORKDIR /usr/src/app
13+
14+
ARG db_url="mongodb://db:27017"
15+
ARG db_name="fastapistarter"
16+
17+
# set environment variables
18+
ENV PORT 8000
19+
ENV HOST "0.0.0.0"
20+
ENV WEBHOOKS_PORT 8001
21+
ENV DB_URL=$db_url
22+
ENV DB_NAME=$db_name
23+
24+
# Copy Required Project Assets
25+
COPY ./app/ /app/app
26+
COPY ./main.py /app
27+
COPY ./poetry.lock /app
28+
COPY ./pyproject.toml /app
29+
30+
# Change directories
31+
WORKDIR /app
32+
33+
# Install Project Dependencies
34+
RUN poetry config virtualenvs.create false \
35+
&& poetry install
36+
37+
# Entry Point
38+
CMD ["python3", "main.py", "--host", "127.0.0.1", "--port", "8000"]

README.MD

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# FastAPI + GraphQL Starter
2+
A python starter project using FastAPI and GraphQL. This project leverages docker for containerization and provides the scripts to deploy to Heroku. The starter is created for and used in the <a href="/">Building Python Apps with FastAPI</a> book by <a href="https://eidanrosado.com">Eidan J. Rosado</a>.
3+
4+
### Running Services with Docker
5+
To avoid setting up MongoDB and other such services locally, the team uses Docker. You'll need to install Docker to proceed pulling the image from the team's hub. Contact one of the team admins for access to the hub. To start peripheral services simply execute the following:
6+
7+
```bash
8+
docker-compose up
9+
```
10+
11+
To refresh the image on your local (for server devs), run the following:
12+
13+
```bash
14+
docker build -t fastapistarter -f Dockerfile.web .
15+
```
16+
17+
You can run the one off image and container with the following:
18+
19+
```bash
20+
docker run -d --name fastapistarter -p 8000:8000 -p 8001:8001 fastapistarter
21+
```
22+
23+
## Using Heroku
24+
If you are pushing to your personal stack on Heroku, you'll need to run the dockerization steps above to build the base image and then follow up with the Heroku containerization steps below.
25+
26+
'''bash
27+
heroku container:push --recursive
28+
heroku container:release web
29+
'''
30+
31+
<em>Note: You must do a heroku login or use API tokens to push to the container registry</em>
32+
33+
### Running API Locally
34+
You'll need the following environment variables configured or in a .env file to run the server successfully:
35+
36+
```bash
37+
# FastAPI Setup
38+
export HOST="127.0.0.1"
39+
export PORT=8000
40+
export WEBHOOKS_PORT=8001
41+
42+
# fastapistarter DB Setup
43+
export DB_URL='mongodb://localhost:27017'
44+
export DB_NAME='fastapistarter'
45+
```
46+
47+
The main entry point is main.py, so you can start that file from command line or use whatever execution method is available from your IDE. To install the IDE to interact with GraphQL, look in the SETUP.md for GraphQL Playground installation instructions then simply open the GraphQL Playground to interact with the local server and insert the base url <em>http://127.0.0.1:8000/api</em>. For more detailed instructions, check the wiki.
48+
49+
## Dev Notes
50+
### Viewing Changes
51+
Changes under /app may be picked up by the auto-refresh (no need to restart server). To understand how to use the playground to run queries, please reference the following: <a href="https://graphql.org/learn/queries/">GraphQL Queries Reference</a>

app/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__version__ = '0.1.0'

app/config/__init__.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from pydantic import BaseSettings
2+
3+
class CommonSettings(BaseSettings):
4+
APP_NAME: str = "FastAPI GraphQL Starter"
5+
DEBUG_MODE: bool = False
6+
7+
class ServerSettings(BaseSettings):
8+
HOST: str = "127.0.0.1"
9+
PORT: int = 8000
10+
WEBHOOKS_PORT: int = 8001
11+
12+
13+
class DatabaseSettings(BaseSettings):
14+
DB_URL: str = ''
15+
DB_NAME: str = ''
16+
17+
class Settings(CommonSettings, ServerSettings, DatabaseSettings):
18+
class Config:
19+
env_file = '.env'
20+
env_file_encoding = 'utf-8'
21+
22+
settings = Settings()

app/graphql/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import strawberry
2+
from strawberry.asgi import GraphQL
3+
4+
from app.resolvers.hello.resolve_hello import *
5+
6+
7+
@strawberry.type
8+
class Query:
9+
hello_world = strawberry.field(resolve_hello_world)
10+
11+
12+
schema = strawberry.Schema(query=Query())
13+
graphql_app = GraphQL(schema, debug=True, )
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from __future__ import annotations
2+
import strawberry
3+
from dataclasses import dataclass
4+
from dataclasses_json import dataclass_json, LetterCase
5+
6+
7+
@dataclass_json(letter_case=LetterCase.CAMEL)
8+
@dataclass
9+
@strawberry.type
10+
class HelloResponse:
11+
message: str = None
12+
timestamp: str = None

app/resolvers/hello/resolve_hello.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import datetime
2+
3+
from app.models.hello.hello_response_models \
4+
import HelloResponse
5+
6+
7+
async def resolve_hello_world() -> HelloResponse:
8+
return HelloResponse("Hello World!", datetime.datetime.now())

docker-compose.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: '3.8'
2+
3+
services:
4+
mongo:
5+
image: mongo
6+
restart: always
7+
ports:
8+
- 27017:27017
9+
fastapistarter:
10+
image: fastapistarter
11+
restart: always
12+
ports:
13+
- 8000:8000
14+
- 8001:8001
15+
links:
16+
- mongo
17+
environment:
18+
- PORT=8000
19+
- DB_URL=mongodb://mongo:27017
20+
- DB_NAME=fastapistarter

main.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import datetime
2+
import uvicorn
3+
from fastapi import FastAPI
4+
5+
from app.config import settings
6+
from app.graphql import graphql_app
7+
8+
app = FastAPI()
9+
app.mount('/graph', graphql_app)
10+
11+
12+
@app.on_event('startup')
13+
async def startup():
14+
public_paths = {'/', '/graph'},
15+
16+
17+
@app.get("/")
18+
async def root():
19+
return {"message": {
20+
"app_name": settings.APP_NAME,
21+
"system_time": datetime.datetime.now()
22+
}}
23+
24+
25+
if __name__ == "__main__":
26+
uvicorn.run(
27+
"main:app",
28+
host=settings.HOST,
29+
reload=True,
30+
port=settings.PORT,
31+
debug=False
32+
)

0 commit comments

Comments
 (0)