Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

About

Heroes tutorial with FastAPI, SqlModel, postgresql 14 and docker-compose

4. (FastAPI + SqlModel) Hero 튜토리얼 실행

SqlModel 의 Hero 튜토리얼을 FastAPI 프레임워크로 구현한 프로젝트

1) 실행화면 캡쳐

Backend: api

fastapi docs screen
<그림> FastAPI /docs 화면

Storage: db

$ psql -d company_db -U tonyne -h localhost -p 5432 -W
Password:
psql (14.5)
Type "help" for help.

company_db=# select * from hero;
    name    |   secret_name    | age | id
------------+------------------+-----+----
 Deadpond   | Dive Wilson      |     |  1
 Rusty-Man  | Tommy Sharp      |  48 |  2
 Dormammu   | Unknown          |     |  3
 Spider-Boy | Pedro Parqueador |  21 |  4
(4 rows)

Frontend: web

Vue heroes screen{: width="580"}
<그림> Vue /heroes 화면

2) API 샘플

(1) create hero : POST /heroes

# insert with HeroCreate
$ curl -X POST "http://localhost:58000/heroes/" -H "Content-Type: application/json" -d '''
{"name": "ABC Teacher", "secret_name": "foo bar", "age": 35}
'''
{"name":"ABC Teacher","secret_name":"foo bar","age":35,"id":5}%


# select by ID=5
$ curl -X GET "http://localhost:58000/hero/5"
{"name":"ABC Teacher","secret_name":"foo bar","age":35,"id":5}%

(2) update hero{id} : PATCH /heroes/{id}

# update whole-data by ID=5
$ curl -X PATCH "http://localhost:58000/heroes/5" -H "Content-Type: application/json" -H 'Accept: application/json' -d '''
{"name": "ABC Teacher (Extra)", "secret_name": "foo bar", "age": 55}
'''
{"name":"ABC Teacher","secret_name":"foo bar","age":35,"id":5}%


# update partial-data by ID=5
$ curl -X PATCH "http://localhost:58000/heroes/5" -H "Content-Type: application/json" -H 'Accept: application/json' -d '''
{"name": "ABC Super Teacher (Extra)"}
'''
{"name":"ABC Super Teacher (Extra)","secret_name":"foo bar","age":55,"id":5}%


# select by ID=5
$ curl -X GET -H 'Accept: application/json' "http://localhost:58000/hero/5"
{"name":"ABC Teacher Teacher (Extra)","secret_name":"foo bar","age":55,"id":5}%

(3) delete hero{id} : DELETE /heroes/{id}

# delete by ID=5
$ curl -X DELETE -H 'Accept: application/json' "http://localhost:58000/heroes/5"
{"ok":true}%


# select by ID=5 => 404 Error
$ curl -X GET -H 'Accept: application/json' "http://localhost:58000/hero/5"
{"detail":"Hero not found"}%

(4) select hero or heroes

  • GET /heroes/last
  • GET /heroes
  • GET /hero/2
$ curl -X GET "http://localhost:58000/heroes/last"
{"name":"Spider-Boy","secret_name":"Pedro Parqueador","age":21,"team_id":null,"id":4}%
  • select with relations : GET /heroes/1
{
  "name": "Deadpond",
  "secret_name": "Dive Wilson",
  "age": null,
  "team_id": 1,
  "id": 1,
  "team": {
    "name": "서울팀",
    "headquarters": "종로구",
    "id": 1
  }
}

(5) create team : POST /teams

$ curl -X POST "http://localhost:8000/teams/" -H "Content-Type: application/json" -d '''
{"name": "뉴욕팀", "headquarters": "뉴욕시청", "heroes": []}
'''
{"name":"뉴욕팀","headquarters":"뉴욕시청","id":6}%

$ curl -X POST "http://localhost:8000/teams/" -H "Content-Type: application/json" -d '''
{"name": "뉴욕팀", "headquarters": "뉴욕시청", "heroes": [
  {"name":"Spider-Boy","secret_name":"Pedro Parqueador","age":21,"id":4}
]}
'''
{"name":"뉴욕팀","headquarters":"뉴욕시청","id":7}%

(6) update team{id} : PATCH /teams/{id}

# update partial-data by ID=5
$ curl -X PATCH "http://localhost:8000/teams/6" -H "Content-Type: application/json" -H 'Accept: application/json' -d '''
{"name": "뉴욕팀 Super", "headquarters": "뉴욕시청 공원", "heroes": [
  {"name":"Spider-Boy","secret_name":"Pedro Parqueador","age":21,"id":4}
]}
'''
{"name":"뉴욕팀 Super","headquarters":"뉴욕시청 공원","id":6}%

(3) delete team{id} : DELETE /teams/{id}

# delete by ID=5
$ curl -X DELETE -H 'Accept: application/json' "http://localhost:58000/teams/5"
{"ok":true}%


# select by ID=5 => 404 Error
$ curl -X GET -H 'Accept: application/json' "http://localhost:58000/teams/5"
{"detail":"Team not found"}%

(4) select team or teams

  • GET /teams/last
  • GET /teams
  • GET /team/2
$ curl -X GET "http://localhost:58000/teams/last"
{"name":"Spider-Boy","secret_name":"Pedro Parqueador","age":21,"team_id":null,"id":4}%
  • select with relations : GET /teams/1
{
  "name": "서울팀",
  "headquarters": "종로구",
  "id": 1,
  "heroes": [
    {
      "name": "Deadpond",
      "secret_name": "Dive Wilson",
      "age": null,
      "team_id": 1,
      "id": 1
    },
    {
      "name": "Rusty-Man",
      "secret_name": "Tommy Sharp",
      "age": 48,
      "team_id": 1,
      "id": 2
    }
  ]
}

3) tutorials

(0) remove heroes and teams : GET /tutorial/0

  • delete select(Hero).where(Hero.name.match("%Tutorial%"))
  • delete select(Team).where(Team.name.match("%Tutorial%"))

(1) create heroes and teams : GET /tutorial/1

  • create teams: ['Tutorial Preventers', 'Tutorial Z-Force']
  • create heroes: ['Tutorial Deadpond', 'Tutorial Rusty-Man', 'Tutorial Spider-Boy']
    • 'Tutorial Deadpond'.team = 'Tutorial Z-Force'
    • 'Tutorial Rusty-Man'.team = 'Tutorial Preventers'

(2) select hero and team : GET /tutorial/2

  • select hero select(Hero).where(Hero.name == "Tutorial Spider-Boy")
  • select team select(Team).where(Team.id == hero_spider_boy.team_id)

(3) update hero with team : GET /tutorial/3

  • update hero "Tutorial Spider-Boy"
    • hero_spider_boy.team = team_preventers (팀 배정)

(4) delete team and update heroes : GET /tutorial/4

  • delete team "Tutorial Preventers"
    • updated hero with none team

4) pytest

(1) tests/main_test.py

  • test_hello : fastapi 작동 여부
  • test_hero : GET /heroes/last 작동 여부와 HeroRead 변환
  • test_aiohttp_with_every_client : 1000 번 GET /heroes/ 호출
    • resp.status == 200 검사
$ poetry run pytest tests --log-cli-level=DEBUG
============================== test session starts ===============================
platform darwin -- Python 3.9.13, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/bgmin/Workspaces/python/sqlmodel/sqlmodel-pg-api/smp-api
plugins: anyio-3.6.1
collected 6 items

tests/main_test.py::test_hello
tests/main_test.py::test_read_items
tests/main_test.py::test_read_item
tests/main_test.py::test_create_item
tests/main_test.py::test_update_item
tests/main_test.py::test_delete_item

tests/main_test.py ......                                                  [100%]

=============================== 6 passed in 0.64s ================================

(2) tests/hero_test.py

  • test_read_items, test_read_item : select 테스트
  • test_create_item : create 테스트
  • test_update_item : update 테스트
  • test_delete_item : delete 테스트

(3) tests/team_test.py

  • test_read_groups, test_read_group : select 테스트
  • test_create_group : create 테스트
  • test_update_group : update 테스트
  • test_delete_group: delete 테스트

5) mongoDB 관련 API

(1) /files : CSV 파일 업로드 및 JSON insert

$ curl -F 'file=@../assets/data/test.csv' -X POST "http://localhost:58000/files/upload"
[{"name":"Alice","age":"20","height":"62","weight":"120.6","_id":"1"},{"name":"Freddie","age":"21","height":"74","weight":"190.6","_id":"2"},{"name":"Bob","age":"17","height":"68","weight":"120.0","_id":"3"}]%

$ curl -X GET "http://localhost:8000/files/test"
[{"_id":"1","name":"Alice","age":20,"height":62,"weight":120.6},{"_id":"2","name":"Freddie","age":21,"height":74,"weight":190.6},{"_id":"3","name":"Bob","age":17,"height":68,"weight":120.0}]%

(2) /books : Book 모델 insert

$ curl -X POST "http://localhost:8000/books/" -H "Content-Type: application/json" -d '''{ "_id": "066de609-b04a-4b30-b46c-32537c7f1f6e",
  "title": "Don Quixote",
  "author": "Miguel de Cervantes",
  "synopsis": "..."
}
'''
{"_id":"066de609-b04a-4b30-b46c-32537c7f1f6e","title":"Don Quixote","author":"Miguel de Cervantes","synopsis":"..."}%

$ curl -X PUT "http://localhost:8000/books/066de609-b04a-4b30-b46c-32537c7f1f6e" -H "Content-Type: application/json" -d '''{
  "title": "Don Quixote",
  "author": "Miguel de Cervantes",
  "synopsis": "Don Quixote is a Spanish novel by Miguel de Cervantes..."
}
'''
{"_id":"066de609-b04a-4b30-b46c-32537c7f1f6e","title":"Don Quixote","author":"Miguel de Cervantes","synopsis":"Don Quixote is a Spanish novel by Miguel de Cervantes..."}%

$ curl -X GET "http://localhost:8000/books/"
[{"_id":"066de609-b04a-4b30-b46c-32537c7f1f6e","title":"Don Quixote","author":"Miguel de Cervantes","synopsis":"Don Quixote is a Spanish novel by Miguel de Cervantes..."}]%

4. docker compose 실행

# 도커 컴포즈에서 linux/amd64 이미지 생성 (Mac M1)
$ env DOCKER_DEFAULT_PLATFORM=linux/amd64 docker compose build
[+] Building 650.5s (20/21)
 => [internal] load build definition from Dockerfile                 0.0s
 => => transferring dockerfile: 32B                                  0.0s
 => [internal] load .dockerignore                                    0.0s
 => => transferring context: 34B                                     0.0s
 => [internal] load metadata for docker.io/library/python:3.9-slim   3.1s
...

$ docker compose up -d
[+] Running 2/2
 ⠿ Container smp-db   Created                                        0.0s
 ⠿ Container smp-api  Recreated                                      0.1s
Attaching to smp-api, smp-db
...

$ docker compose down -v
[+] Running 5/0
 ⠿ Container smp-api                Removed                          0.0s
 ⠿ Container smp-db                 Removed                          0.0s
 ⠿ Volume smpapi_data               Removed                          0.0s
 ⠿ Volume smpdb_data                Removed                          0.0s
 ⠿ Network sqlmodel-pg-api_default  Rem...                           0.1s

참고: git

# 신규 리포지토리에 연결시
git init
git add --all
git commit -m "first commit"
git branch -M main
git remote add origin $GITHUB/maxmin93/fastapi-sqlmodel-heroes.git
git push -u origin main

# 기존 리포지토리에 연결시
git remote add origin https://github.com/maxmin93/fastapi-sqlmodel-heroes.git
git branch -M main
git push -u origin main

# 새로운 브랜치 생성/변경
git checkout -b db-mongo

# 새로운 브랜치로 push (최초)
git push --set-upstream origin db-mongo

# main 브랜치로 변경 
git checkout main

# 변경사항 로그 조회
git log --graph --decorate --oneline

# 변경사항 파일 조회
git status -u

# 파일 변경사항 조회 (최신 HEAD와 비교)
git diff ../README.md

# staged 파일 변경사항 조회 (git add 된)
git diff --staged ../README.md

# 파일 변경사항 취소
git restore ../README.md

# 변경 스테이징
git add --all

# branch 반영에 대한 Pull request 처리 후, main 에서 
# tag 생성 및 반영 (=> release 생성)
#   - 또는 모든 tags 반영 : git push origin --tags
git tag -a v0.0.3 -m "add mongoDB and APIs with csv upload"
git push origin v0.0.3

About

Heroes tutorial with FastAPI, SqlModel, postgresql 14 and docker-compose

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages