diff --git a/back/db.py b/back/db.py new file mode 100644 index 0000000..bb5060b --- /dev/null +++ b/back/db.py @@ -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) diff --git a/main.py b/main.py index 7265b8b..4a25397 100644 --- a/main.py +++ b/main.py @@ -1,43 +1,36 @@ -from fastapi import FastAPI - +from fastapi import FastAPI, Depends from typing import List +from sqlalchemy.orm import Session + 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.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 { "message": "People list has been succesfully imported", - "records_created": 10 + "records_created": count } @app.get("/average_age", response_model=List[AverageAgeByCountry]) -async def read_average_age() -> List[AverageAgeByCountry]: - return [ - {'country': 'FR', 'average_age': 15.0}, - {'country': 'BE', 'average_age': 25.0}, - {'country': 'DE', 'average_age': 23.3}, - {'country': 'IT', 'average_age': 45.0}, - ] +async def read_average_age(db: Session = Depends(get_db)) -> List[AverageAgeByCountry]: + return [AverageAgeByCountry(**a) for a in get_average_age_by_country(db)] @app.get("/count_by_country", response_model=List[CountByCountry]) -async def read_count_by_country() -> List[CountByCountry]: - return [ - {'country': 'FR', 'people_count': 2}, - {'country': 'BE', 'people_count': 4}, - {'country': 'DE', 'people_count': 3}, - {'country': 'IT', 'people_count': 1}, - ] +async def read_count_by_country(db: Session = Depends(get_db)) -> List[CountByCountry]: + return [CountByCountry(**a) for a in count_people_by_country(db)] @app.get("/gender_repartition/{country}", response_model=GenderRepartition) -async def read_count_by_gender(country: str) -> GenderRepartition: - return { - "female_proportion": 33.3, - "male_proportion": 66.6 - } +async def read_count_by_gender(country: str, db: Session = Depends(get_db)) -> GenderRepartition: + return GenderRepartition(**get_gender_repartition_by_country(db, country))