-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
248 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,182 @@ | ||
from fastapi import FastAPI | ||
|
||
from app.db import database, User | ||
from fastapi import FastAPI, HTTPException | ||
from fastapi.middleware.cors import CORSMiddleware | ||
from fastapi.responses import JSONResponse | ||
from pydantic import BaseModel, Field | ||
from pydantic_settings import BaseSettings | ||
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey | ||
from sqlalchemy.ext.declarative import declarative_base | ||
from sqlalchemy.orm import sessionmaker, relationship | ||
from prometheus_fastapi_instrumentator import Instrumentator | ||
|
||
app = FastAPI(title="FastAPI, Docker, and Traefik") | ||
instrumentator = Instrumentator().instrument(app) | ||
# Database configuration | ||
import os | ||
|
||
class Settings(BaseSettings): | ||
db_url: str = Field(..., env='DATABASE_URL') | ||
|
||
settings = Settings(db_url=os.environ['DATABASE_URL']) | ||
|
||
#from .config import settings | ||
#database = databases.Database(settings.db_url) | ||
#DATABASE_URL = "postgresql://postgres:postgres123@192.168.1.30/db_app001" | ||
|
||
engine = create_engine(settings.db_url) | ||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) | ||
|
||
Base = declarative_base() | ||
|
||
# Define User model | ||
class User(Base): | ||
__tablename__ = "users" | ||
|
||
id = Column(Integer, primary_key=True, index=True) | ||
name = Column(String, index=True) | ||
email = Column(String, index=True) | ||
course_id = Column(Integer, ForeignKey("courses.id_cours")) | ||
|
||
course = relationship("Course", back_populates="users") | ||
|
||
# Define Course model | ||
class Course(Base): | ||
__tablename__ = "courses" | ||
|
||
id_cours = Column(Integer, primary_key=True, index=True) | ||
course_name = Column(String, index=True) | ||
|
||
users = relationship("User", back_populates="course") | ||
|
||
# Create tables in the database | ||
Base.metadata.create_all(bind=engine) | ||
|
||
# FastAPI app setup | ||
app = FastAPI() | ||
|
||
# Prometheus monitoring setup | ||
Instrumentator().instrument(app).expose(app) | ||
|
||
# CORS middleware | ||
app.add_middleware( | ||
CORSMiddleware, | ||
allow_origins=["*"], | ||
allow_credentials=True, | ||
allow_methods=["*"], | ||
allow_headers=["*"], | ||
) | ||
|
||
# Pydantic models for request and response | ||
class UserCreate(BaseModel): | ||
name: str | ||
email: str | ||
|
||
class CourseCreate(BaseModel): | ||
course_name: str | ||
|
||
class UserResponse(UserCreate): | ||
id: int | ||
|
||
class CourseResponse(CourseCreate): | ||
id_cours: int | ||
|
||
# Endpoints | ||
@app.post("/users/", response_model=UserResponse) | ||
def create_user(user: UserCreate): | ||
db = SessionLocal() | ||
db_user = User(**user.dict()) | ||
db.add(db_user) | ||
db.commit() | ||
db.refresh(db_user) | ||
db.close() | ||
return db_user | ||
|
||
@app.put("/users/{user_id}", response_model=UserResponse) | ||
def update_user(user_id: int, user: UserCreate): | ||
db = SessionLocal() | ||
db_user = db.query(User).filter(User.id == user_id).first() | ||
if db_user: | ||
db_user.name = user.name | ||
db_user.email = user.email | ||
db.commit() | ||
db.refresh(db_user) | ||
db.close() | ||
return db_user | ||
|
||
@app.get("/users/{user_id}", response_model=UserResponse) | ||
def read_user(user_id: int): | ||
db = SessionLocal() | ||
db_user = db.query(User).filter(User.id == user_id).first() | ||
db.close() | ||
if db_user: | ||
return db_user | ||
else: | ||
raise HTTPException(status_code=404, detail="User not found") | ||
|
||
@app.get("/users/", response_model=list[UserResponse]) | ||
def read_users(skip: int = 0, limit: int = 10): | ||
db = SessionLocal() | ||
users = db.query(User).offset(skip).limit(limit).all() | ||
db.close() | ||
return users | ||
|
||
@app.delete("/users/{user_id}", response_model=UserResponse) | ||
def delete_user(user_id: int): | ||
db = SessionLocal() | ||
db_user = db.query(User).filter(User.id == user_id).first() | ||
if db_user: | ||
db.delete(db_user) | ||
db.commit() | ||
db.close() | ||
return db_user | ||
else: | ||
db.close() | ||
raise HTTPException(status_code=404, detail="User not found") | ||
|
||
@app.get("/") | ||
async def read_root(): | ||
return await User.objects.all() | ||
@app.post("/courses/", response_model=CourseResponse) | ||
def create_course(course: CourseCreate): | ||
db = SessionLocal() | ||
db_course = Course(**course.dict()) | ||
db.add(db_course) | ||
db.commit() | ||
db.refresh(db_course) | ||
db.close() | ||
return db_course | ||
|
||
@app.put("/courses/{course_id}", response_model=CourseResponse) | ||
def update_course(course_id: int, course: CourseCreate): | ||
db = SessionLocal() | ||
db_course = db.query(Course).filter(Course.id_cours == course_id).first() | ||
if db_course: | ||
db_course.course_name = course.course_name | ||
db.commit() | ||
db.refresh(db_course) | ||
db.close() | ||
return db_course | ||
|
||
@app.on_event("startup") | ||
async def startup(): | ||
# Expose prometheus metrics using the Instrumentator | ||
# https://github.com/trallnag/prometheus-fastapi-instrumentator | ||
instrumentator.expose(app) | ||
if not database.is_connected: | ||
await database.connect() | ||
# create a dummy entry | ||
await User.objects.get_or_create(email="test@test.com") | ||
@app.get("/courses/{course_id}", response_model=CourseResponse) | ||
def read_course(course_id: int): | ||
db = SessionLocal() | ||
db_course = db.query(Course).filter(Course.id_cours == course_id).first() | ||
db.close() | ||
if db_course: | ||
return db_course | ||
else: | ||
raise HTTPException(status_code=404, detail="Course not found") | ||
|
||
@app.get("/courses/", response_model=list[CourseResponse]) | ||
def read_courses(skip: int = 0, limit: int = 10): | ||
db = SessionLocal() | ||
courses = db.query(Course).offset(skip).limit(limit).all() | ||
db.close() | ||
return courses | ||
|
||
@app.on_event("shutdown") | ||
async def shutdown(): | ||
if database.is_connected: | ||
await database.disconnect() | ||
@app.delete("/courses/{course_id}", response_model=CourseResponse) | ||
def delete_course(course_id: int): | ||
db = SessionLocal() | ||
db_course = db.query(Course).filter(Course.id_cours == course_id).first() | ||
if db_course: | ||
db.delete(db_course) | ||
db.commit() | ||
db.close() | ||
return db_course | ||
else: | ||
db.close() | ||
raise HTTPException(status_code=404, detail="Course not found") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,36 @@ | ||
asyncpg==0.29.0 | ||
fastapi==0.106.0 | ||
ormar==0.12.2 | ||
annotated-types==0.6.0 | ||
anyio==3.7.1 | ||
certifi==2023.11.17 | ||
click==8.1.7 | ||
colorama==0.4.6 | ||
dnspython==2.4.2 | ||
email-validator==2.1.0.post1 | ||
fastapi==0.105.0 | ||
greenlet==3.0.3 | ||
h11==0.14.0 | ||
httpcore==1.0.2 | ||
httptools==0.6.1 | ||
httpx==0.26.0 | ||
idna==3.6 | ||
itsdangerous==2.1.2 | ||
Jinja2==3.1.2 | ||
MarkupSafe==2.1.3 | ||
orjson==3.9.10 | ||
prometheus-client==0.19.0 | ||
prometheus-fastapi-instrumentator==6.1.0 | ||
psycopg2-binary==2.9.9 | ||
pydantic==2.5.3 | ||
pydantic-extra-types==2.2.0 | ||
pydantic-settings==2.1.0 | ||
pydantic_core==2.14.6 | ||
python-dotenv==1.0.0 | ||
python-multipart==0.0.6 | ||
PyYAML==6.0.1 | ||
sniffio==1.3.0 | ||
SQLAlchemy==2.0.23 | ||
starlette==0.27.0 | ||
typing_extensions==4.9.0 | ||
ujson==5.9.0 | ||
uvicorn==0.25.0 | ||
prometheus-fastapi-instrumentator==6.1.0 | ||
watchfiles==0.21.0 | ||
websockets==12.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.