100일 챌린지/빅데이터기반 인공지능 융합 서비스 개발자

Day 87 - fastapi로 CRUD 프로그램 만들기

ksyke 2024. 12. 2. 16:30

목차

    main.py

    import fastapi
    from fastapi.templating import Jinja2Templates
    from starlette.requests import Request
    from routers.DeptRouter import router
    
    app=fastapi.FastAPI()
    template=Jinja2Templates('templates')
    
    app.include_router(router=router)
    
    @app.get("/")
    def index(req:Request):
        return template.TemplateResponse('index.html',{'request':req})
    @app.get("/intro")
    def intro(req:Request):
        return template.TemplateResponse('intro.html',{'request':req})

    DataConfig.py

    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker,declarative_base
    
    engine=create_engine("sqlite:///./dept.db", connect_args={"check_same_thread": False})
    sessionLocal=sessionmaker(bind=engine,autoflush=False,autocommit=False)
    Base=declarative_base()
    
    def get_db():
        db=sessionLocal()
        try:
            yield db
        finally:
            db.close()

    models.py

    from sqlalchemy import Column, Integer, String
    
    from DataConfig import Base, engine
    
    class Dept(Base):
        __tablename__='dept'
        deptno=Column(Integer,primary_key=True,index=True,autoincrement=True)
        dname=Column(String(10),nullable=False)
        loc=Column(String)
    
    if __name__=='__main__':
        Base.metadata.create_all(engine)

    routers/DeptRouter.py

    import mysql.connector
    from fastapi import APIRouter, Depends
    from fastapi.requests import Request
    from fastapi.templating import Jinja2Templates
    from pydantic import BaseModel
    from sqlalchemy.orm import Session
    
    from DataConfig import get_db
    from models import Dept
    
    router=APIRouter(prefix='/dept')
    template=Jinja2Templates('templates')
    
    class DeptVo(BaseModel):
        deptno:int=0
        dname:str
        loc:str
    
        def __str__(self):
            return str(self.deptno)+","+self.dname+','+self.loc
    
    
    # def Outter(cb):
    #     print('outer')
    #     def Inner(sql):
    #         print('inner')
    #         return cb(sql)
    #     return Inner
    #
    # @Outter
    # def getList(sql):
    #     try:
    #         arr = []
    #         conn = mysql.connector.connect(
    #             host="localhost",
    #             user="scott",
    #             password="tiger",
    #             database="xe"
    #         )
    #
    #         mycursor = conn.cursor()
    #
    #         mycursor.execute(sql)
    #
    #         for row in mycursor.fetchall():
    #             arr.append(DeptVo(deptno=row[0], dname=row[1], loc=row[2]))
    #         return arr
    #     finally:
    #         conn.close()
    
    @router.get("/")
    def list(req:Request,db:Session=Depends(get_db)):
        # arr=getList("SELECT * FROM dept")
        arr=[]
        for bean in db.query(Dept).all():
            arr.append(DeptVo(deptno=bean.deptno,dname=bean.dname,loc=bean.loc))
        return template.TemplateResponse('dept/list.html',{'request':req,'list':arr})
    
    
    @router.get('/add')
    def add(req:Request):
        return template.TemplateResponse('dept/add.html',{'request':req})
    
    @router.post('/')
    def add(dept:DeptVo,db:Session=Depends(get_db)):
        print('add',dept)
        bean=Dept(dname=dept.dname,loc=dept.loc)
        db.add(bean)
        db.commit()
        return {"result":"success"}
    
    @router.get('/{deptno}')
    def add(req:Request,deptno:int,db:Session=Depends(get_db)):
        bean=db.query(Dept).filter(Dept.deptno == deptno).first()
        ## 수정
        # bean.loc='edit'
        # db.commit()
        # print(bean)
        ## 삭제
        # db.delete(bean)
        # db.commit()
        return template.TemplateResponse('dept/detail.html',{'request':req,'bean':bean})
        # return {}

    templates/

    index

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    </head>
    <body>
    <nav>
      <a href="/">home</a>
      <a href="/intro">intro</a>
      <a href="/dept/">dept</a>
      <a href="/login/">login</a>
    </nav>
    <hr/>
    <div class="container">
      <h2>index page</h2>
    </div>
    </body>
    </html>

    intro

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    </head>
    <body>
    <nav>
      <a href="/">home</a>
      <a href="/intro">intro</a>
      <a href="/dept/">dept</a>
      <a href="/login/">login</a>
    </nav>
    <hr/>
    <div class="container">
      <h2>intro page</h2>
    </div>
    </body>
    </html>

    dept/

    list

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    </head>
    <body>
    <nav>
      <a href="/">home</a>
      <a href="/intro">intro</a>
      <a href="/dept/">dept</a>
      <a href="/login/">login</a>
    </nav>
    <hr/>
    <div class="container">
      <h2>page</h2>
        <table class="table">
            <thead>
                <tr>
                    <th>deptno</th>
                    <th>dname</th>
                    <th>loc</th>
                </tr>
            </thead>
            <tbody>
                {% for bean in list %}
                <tr>
                    <td><a href="{{bean.deptno}}">{{bean.deptno}}</a></td>
                    <td><a href="{{bean.deptno}}">{{bean.dname}}</a></td>
                    <td><a href="{{bean.deptno}}">{{bean.loc}}</a></td>
                </tr>
                {% endfor %}
            </tbody>
        </table>
        <a href="add" class="btn btn-primary btn-block" role="button">입력</a>
    </div>
    </body>
    </html>

    add

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    </head>
    <body>
    <nav>
      <a href="/">home</a>
      <a href="/intro">intro</a>
      <a href="/dept/">dept</a>
      <a href="/login/">login</a>
    </nav>
    <hr/>
    <div class="container">
      <h2>page</h2>
        <form>
            <div class="form-group">
                <input type="text" name="dname" class="form-control" >
            </div>
            <div class="form-group">
                <input type="text" name="loc" class="form-control" >
            </div>
            <div class="form-group">
                <button class="btn btn-primary btn-block">입력</button>
            </div>
        </form>
        <script type="text/javascript">
            const form=document.querySelector('form')
            const [input1,input2]=form.querySelectorAll('input')
            form.onsubmit=e=>{
                e.preventDefault();
                console.log('입력',input1,input2);
                fetch('/dept/',{
                    method:'POST',
                    body:JSON.stringify({'dname':input1.value,'loc':input2.value}),
                    headers: {
                    "Content-Type": "application/json"
                    }
                }).then(e=>e.json()).then(e=>location.href='/dept/').catch(alert)
            };
        </script>
    </div>
    </body>
    </html>

    detail

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    </head>
    <body>
    <nav>
      <a href="/">home</a>
      <a href="/intro">intro</a>
      <a href="/dept/">dept</a>
      <a href="/login/">login</a>
    </nav>
    <hr/>
    <div class="container">
      <h2>detail page</h2>
            <form>
            <div class="form-group">
                <input type="text" name="deptno" class="form-control" value="{{bean.deptno}}">
            </div>
            <div class="form-group">
                <input type="text" name="dname" class="form-control" value="{{bean.dname}}">
            </div>
            <div class="form-group">
                <input type="text" name="loc" class="form-control" value="{{bean.loc}}" >
            </div>
            <div class="form-group">
                <button class="btn btn-primary btn-block">수정</button>
            </div>
        </form>
    </div>
    </body>
    </html>

    login/login

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    </head>
    <body>
    <nav>
      <a href="/">home</a>
      <a href="/intro">intro</a>
      <a href="/dept/">dept</a>
      <a href="/login/">login</a>
    </nav>
    <hr/>
    <div class="container">
      <h2>page</h2>
    </div>
    </body>
    </html>