Skip to content
This repository was archived by the owner on Feb 19, 2023. It is now read-only.

Commit b261a98

Browse files
authored
chore: updates and clean up (#10)
1 parent c637882 commit b261a98

File tree

14 files changed

+133
-22
lines changed

14 files changed

+133
-22
lines changed

.env_example

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
1+
# app
2+
ENCRYPT_KEY=
3+
SECRET_KEY=
14
ENV=dev
25
PROJECT_NAME=fastapi_backend_base
36
VERSION=v1
47

8+
# Database
59
POSTGRES_USER=fastapibackendbase
610
POSTGRES_PASSWORD=fastapibackendbase0987
711
POSTGRES_DB=fastapibackendbase
812
POSTGRES_HOST=db
913
POSTGRES_PORT=5432
1014

11-
ENCRYPT_KEY=
12-
SECRET_KEY=
13-
15+
# Nginx
1416
NGINX_HOST=localhost
1517
UPSTREAMS=/:backend:8000
18+
ENABLE_SSL=
19+
CERTBOT_EMAIL=
20+
DOMAIN_LIST=
1621

22+
# Redis
1723
REDIS_HOST=redis
1824
REDIS_PORT=6379

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
<a href="https://github.com/nickatnight/fastapi-backend-base/actions">
33
<img alt="GitHub Actions status" src="https://github.com/nickatnight/fastapi-backend-base/actions/workflows/main.yml/badge.svg">
44
</a>
5+
<a href="https://github.com/nickatnight/fastapi-backend-base/releases"><img alt="Release Status" src="https://img.shields.io/github/v/release/nickatnight/fastapi-backend-base"></a>
56
</p>
67

78

89
# fastapi-backend-base
910

10-
Small base project to build and deploy a fastapi backend..batteries included.
11+
Small base project I use to build and deploy fastapi backends..batteries included. Basically a stripped down version of [this](https://github.com/tiangolo/full-stack-fastapi-postgresql) and [this](https://github.com/jonra1993/fastapi-alembic-sqlmodel-async) repo...with some extra bells and whistles.
1112

1213
## Features
1314
* **Docker Compose** integration and optimization for local development.

backend/requirements/prod.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-r base.txt

backend/requirements/staging.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-r base.txt

backend/src/api/routes.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from fastapi import APIRouter, status
22
from fastapi.responses import PlainTextResponse
33

4-
from src.api.v1 import health
4+
from src.api.v1 import health, meme
55

66

77
home_router = APIRouter()
@@ -14,3 +14,4 @@ async def home():
1414

1515
api_router = APIRouter()
1616
api_router.include_router(health.router)
17+
api_router.include_router(meme.router)

backend/src/api/v1/meme.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from fastapi import APIRouter, Depends, Query
2+
from sqlalchemy.ext.asyncio import AsyncSession
3+
from sqlmodel import select
4+
5+
from src.db.session import get_session
6+
from src.models.meme import Meme
7+
from src.schemas.common import IGetResponseBase
8+
from src.schemas.meme import IMemeRead
9+
10+
11+
router = APIRouter()
12+
13+
14+
@router.get(
15+
"/meme/list",
16+
response_description="List all meme instances",
17+
response_model=IGetResponseBase[IMemeRead],
18+
tags=["memes"],
19+
)
20+
async def memes(
21+
skip: int = Query(0, ge=0),
22+
limit: int = Query(100, ge=1),
23+
session: AsyncSession = Depends(get_session),
24+
) -> IGetResponseBase[IMemeRead]:
25+
result = await session.execute(
26+
select(Meme).offset(skip).limit(limit).order_by(Meme.created_at.desc())
27+
)
28+
memes = result.scalars().all()
29+
30+
return IGetResponseBase[IMemeRead](data=memes)

backend/src/db/session.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from fastapi import HTTPException
2-
from sqlalchemy.exc import SQLAlchemyError
31
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
42
from sqlalchemy.orm import sessionmaker
53
from sqlmodel import SQLModel
@@ -34,14 +32,4 @@ async def get_session() -> AsyncSession:
3432
# after commit.
3533
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
3634
async with async_session() as session:
37-
try:
38-
yield session
39-
await session.commit()
40-
except SQLAlchemyError as sql_ex:
41-
await session.rollback()
42-
raise sql_ex
43-
except HTTPException as http_ex:
44-
await session.rollback()
45-
raise http_ex
46-
finally:
47-
await session.close()
35+
yield session

backend/src/models/__init__.py

Whitespace-only changes.

backend/src/models/base.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import uuid as uuid_pkg
2+
from datetime import datetime
3+
from typing import Optional
4+
5+
from sqlmodel import Field, SQLModel
6+
7+
8+
class BaseModel(SQLModel):
9+
id: uuid_pkg.UUID = Field(
10+
default_factory=uuid_pkg.uuid4,
11+
primary_key=True,
12+
index=True,
13+
nullable=False,
14+
)
15+
updated_at: Optional[datetime]
16+
created_at: Optional[datetime]

backend/src/models/meme.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from datetime import datetime, timezone
2+
3+
from pydantic import BaseConfig, validator
4+
from sqlmodel import Field, SQLModel
5+
6+
from src.models.base import BaseModel
7+
8+
9+
class MemeBase(SQLModel):
10+
submission_id: str = Field(...)
11+
submission_url: str = Field(...)
12+
submission_title: str = Field(...)
13+
permalink: str = Field(...)
14+
author: str = Field(...)
15+
timestamp: datetime = Field(...)
16+
17+
class Config(BaseConfig):
18+
json_encoder = {
19+
datetime: lambda dt: dt.replace(tzinfo=timezone.utc).isoformat(),
20+
}
21+
schema_extra = {
22+
"example": {
23+
"id": "1234-43143-3134-13423",
24+
"submission_id": "nny218",
25+
"submission_title": "This community is so nice. Helps me hodl.",
26+
"submission_url": "https://i.redd.it/gdv6tbamkb271.jpg",
27+
"permalink": "/r/dogecoin/comments/nnvakd/still_holding_keep_the_faith/",
28+
"author": "42points",
29+
"timestamp": "2004-09-16T23:59:58.75",
30+
"created_at": "2004-09-16T23:59:58.75",
31+
}
32+
}
33+
34+
35+
class Meme(BaseModel, MemeBase, table=True):
36+
@validator("created_at", pre=True, always=True)
37+
def set_created_at_now(cls, v):
38+
return v or datetime.now()

0 commit comments

Comments
 (0)