Implementing db querying

This commit is contained in:
2023-01-12 15:27:30 +01:00
parent 2fabf39c7b
commit 21b668d1fb
2 changed files with 101 additions and 23 deletions

85
back/db.py Normal file
View File

@@ -0,0 +1,85 @@
from sqlalchemy import Column, Table, Integer, MetaData, String, select, create_engine
from sqlalchemy.sql import func
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
Base = declarative_base()
class People(Base):
__tablename__ = "people"
id = Column(Integer, primary_key=True, index=True)
name = Column(String)
age = Column(Integer)
gender = Column(String)
country = Column(String)
def create_people_from_list(db, people_list):
count = 0
for p in people_list:
db_people = People(**p.dict())
db.add(db_people)
count += 1
db.commit()
return count
def get_average_age_by_country(db) -> []:
return db.query(People.country.label('country'), func.avg(People.age).label('average_age'))\
.group_by( People.country).all()
def count_people_by_country(db) -> []:
return db.query(People.country.label('country'), func.count(People.id).label('people_count'))\
.group_by( People.country).all()
def get_gender_repartition_by_country(db, country) -> []:
count_women, total = db.query(
select(func.count(People.id).label('count_women')) \
.where(People.gender == 'F') \
.where(People.country == country).subquery(),
select(func.count(People.id).label('total')) \
.where(People.country == country).subquery(),
).first()
female_proportion = count_women / total
return {
"female_proportion": female_proportion,
"male_proportion": 1 - female_proportion
}
meta = MetaData()
Table(
'people', meta,
Column('id', Integer, primary_key=True),
Column('name', String),
Column('age', Integer),
Column('gender', String),
Column('country', String),
)
meta.create_all(engine)

39
main.py
View File

@@ -1,43 +1,36 @@
from fastapi import FastAPI from fastapi import FastAPI, Depends
from typing import List from typing import List
from sqlalchemy.orm import Session
from back.schemas import PeopleList, AverageAgeByCountry, CountByCountry, GenderRepartition from back.schemas import PeopleList, AverageAgeByCountry, CountByCountry, GenderRepartition
from back.db import get_db, create_people_from_list, get_average_age_by_country, \
count_people_by_country, get_gender_repartition_by_country
app = FastAPI() app = FastAPI()
@app.post("/people") @app.post("/people")
async def create_people(people_list: PeopleList) -> dict: async def create_people(people_list: PeopleList, db: Session = Depends(get_db)) -> dict:
count = create_people_from_list(db, people_list.people)
return { return {
"message": "People list has been succesfully imported", "message": "People list has been succesfully imported",
"records_created": 10 "records_created": count
} }
@app.get("/average_age", response_model=List[AverageAgeByCountry]) @app.get("/average_age", response_model=List[AverageAgeByCountry])
async def read_average_age() -> List[AverageAgeByCountry]: async def read_average_age(db: Session = Depends(get_db)) -> List[AverageAgeByCountry]:
return [ return [AverageAgeByCountry(**a) for a in get_average_age_by_country(db)]
{'country': 'FR', 'average_age': 15.0},
{'country': 'BE', 'average_age': 25.0},
{'country': 'DE', 'average_age': 23.3},
{'country': 'IT', 'average_age': 45.0},
]
@app.get("/count_by_country", response_model=List[CountByCountry]) @app.get("/count_by_country", response_model=List[CountByCountry])
async def read_count_by_country() -> List[CountByCountry]: async def read_count_by_country(db: Session = Depends(get_db)) -> List[CountByCountry]:
return [ return [CountByCountry(**a) for a in count_people_by_country(db)]
{'country': 'FR', 'people_count': 2},
{'country': 'BE', 'people_count': 4},
{'country': 'DE', 'people_count': 3},
{'country': 'IT', 'people_count': 1},
]
@app.get("/gender_repartition/{country}", response_model=GenderRepartition) @app.get("/gender_repartition/{country}", response_model=GenderRepartition)
async def read_count_by_gender(country: str) -> GenderRepartition: async def read_count_by_gender(country: str, db: Session = Depends(get_db)) -> GenderRepartition:
return { return GenderRepartition(**get_gender_repartition_by_country(db, country))
"female_proportion": 33.3,
"male_proportion": 66.6
}