inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

172만명의 커뮤니티!! 함께 토론해봐요.

4주 1회차 과제

해결됨

[매일 완독 챌린지] 저자와 함께하는 <FastAPI로 기획에서 출시까지>

is_host / 캘린더 보유 여부 중에 어느 것을 사용할까? 둘 다? is_host 는 반드시 사용할 것 같음 is_host 필드가 있으면 캘린더 라는 다른 엔티티에 의존하지 않고 is_host 만으로 호스트 여부를 판단할 수 있어서 캘린더 보유 여부는 선택적일 것 같음 아래와 같은 정책을 설정해야할 필요가 있을때 is_host 인데 캘린더가 있는 경우 s_host 인데 캘린더가 없는 경우 아니면 '호스트는 최소 하나 이상의 캘린더는 있어야 한다' 같은 정책

  • python
  • aws
  • tdd
  • FastAPI
  • 북-챌린지
ayo 댓글 2 좋아요 0 조회수 49

DB 검색하면 데이터가 없습니다. 라고 나와요. 5시간을 찾아봐도 모르겠어서 문의드려봅니다.

해결됨

남박사의 파이썬으로 실전 웹사이트 만들기

안녕하세요 저의 환경은 윈도우 11이고 파이선 3.12 버전입니다. 몽고DB는 8.2.3 x64입니다. ms 엣지 브라우저 버전 143.0.3650.96 (공식 빌드) (64비트) 입니다. 구글에서 긁어오는게 문제가 있어서 네이버로 변경하여 긁어왔습니다. DB에 35개의 데이터를 넣었습니다. Studio 3T 프로그램으로 검새하면 db . getCollection( "board" ) . find({ $or :[ // {title: { $regex: "이유", $options: "i" }}, { name :{ $regex : "테스터" , $options : "i" }} ] }) 위의 쿼리로 검색을 했을 때 name = '테스터'로 하면 35개 전부 나오고 title = '이유'로 검색하면 3건이 나옵니다. 그런데 웹에서 list.html 검색에서는 0건으로 데이터가 없다고 나옵니다. 원인을 아무리 찾아도 모르겠어서 문의드려봅니다. 위와 같이 네이버에서 검색하여 DB에 넣음 title 이유로 검색하면 3건 name 테스터로 검색하면 35건 조회됩니다. 위와 같이 제목, '이유'로 검색하면 3건이 나와야 하는데 위와 같이 데이터가 없습니다. 라고 나옵니다. # 검색 대상이 한개라도 존재할 경우 query 변수에 $or 리스트를 쿼리 합니다. if len(search_list) > 0: query = {"$or": search_list} print(query) # datas_count = board.count_documents({}) # 정확한 카운트 방식 datas_count = board.count_documents(query) print(datas_count) 위와 같이 print로 값을 보면 {'$or': [{'title': {'regex': '이유'}}]} 0 127.0.0.1 - - [11/Jan/2026 17:42:01] "GET /list?search=0&keyword=이유 HTTP/1.1" 200 - 이렇게 나옵니다. 쿼리는 title 이유라고 잘 들어가는 것 같은데 검색 결과가 0건으로 나옵니다. DB에서 검색이 제대로 안되는걸로 보이는데 어느부분일지 찾지 못하고 있습니다. 아래는 전체 소스코드 입니다. < run.py 전체 코드 > from flask import Flask from flask import request from flask import render_template from flask_pymongo import PyMongo from datetime import datetime from bson.objectid import ObjectId from flask import abort from flask import redirect from flask import url_for import time import math app = Flask(__name__) app.config["MONGO_URI"] = "mongodb://localhost:27017/myweb" mongo = PyMongo(app) @app.template_filter("formatdatetime") def format_datetime(value): if value is None: return "" now_timestamp = time.time() offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp) value = datetime.fromtimestamp((int(value) / 1000)) + offset return value.strftime('%Y-%m-%d %H:%M:%S') @app.route("/list") def lists(): page = request.args.get("page", default=1, type=int) limit = request.args.get("limit", 5, type=int) search = request.args.get("search", -1, type=int) keyword = request.args.get("keyword", type=str) query = {} search_list = [] if search == 0: search_list.append({"title": {"regex": keyword}}) elif search == 1: search_list.append({"contents": {"regex": keyword}}) elif search == 2: search_list.append({"title": {"regex": keyword}}) search_list.append({"contents": {"regex": keyword}}) elif search == 3: search_list.append({"name": {"regex": keyword}}) if len(search_list) > 0: query = {"$or": search_list} print(query) board = mongo.db.board datas = board.find(query).skip((page - 1) * limit).limit(limit) datas_count = board.count_documents(query) print(datas_count) tot_count = datas_count last_page_num = math.ceil(tot_count / limit) block_size = 5 block_num = int((page - 1) / block_size) block_start = int((block_size * block_num) + 1) block_last = math.ceil(block_start + (block_size - 1)) return render_template( "list.html", datas=datas, datas_count=datas_count, limit=limit, page=page, block_start=block_start, block_last=block_last, last_page_num=last_page_num, search=search, keyword=keyword) @app.route("/view/<idx>") def board_view(idx): if idx is not None: page = request.args.get("page") search = request.args.get("search") keyword = request.args.get("keyword") board = mongo.db.board data = board.find_one({"_id": ObjectId(idx)}) if data is not None: result = { "id": data.get("_id"), "name": data.get("name"), "title": data.get("title"), "contents": data.get("contents"), "pubdate": data.get("pubdate"), "view": data.get("view") } return render_template("view.html", result=result, page=page, search=search, keyword=keyword) return abort(404) @app.route("/write", methods=["GET", "POST"]) def board_write(): if request.method == "POST": name = request.form.get("name") title = request.form.get("title") contents = request.form.get("contents") print(name, title, contents) current_utc_time = round(datetime.utcnow().timestamp() * 1000) board = mongo.db.board post = { "name": name, "title": title, "contents": contents, "pubdate": current_utc_time, "view": 0 } x = board.insert_one(post) print(x.inserted_id) return redirect(url_for("board_view", idx=x.inserted_id)) else: return render_template("write.html") if __name__ == "__main__": app.run(debug=True, port=9000) < list.html 전체 코드 > <script> function search() { var v_search = document.getElementById("search").value; var v_keyword = document.getElementById("keyword").value; if(v_search == "" || v_keyword == "") { return false; } else { self.location.href = "{{url_for('lists')}}?search=" + v_search + "&keyword=" + v_keyword; } } </script> <!-- % if datas_count() > 0 %} # Deprecated 됨--> {% if datas_count > 0 %} <table> <thead> <tr> <td>번호</td> <td>제목</td> <td>이름</td> <td>날짜</td> <td>조회수</td> </tr> </thead> <tbody> <!-- 반복되는 구간 --> {% for data in datas %} <tr> <td>{{loop.index + ((page - 1) * limit)}}</td> <td><a href="{{url_for('board_view', idx=data._id, page=page, search=search, keyword=keyword)}}">{{data.title}}</a></td> <td>{{data.name}}</td> <td>{{data.pubdate | formatdatetime}}</td> <td>{{data.view}}</td> </tr> {% endfor %} <!-- 반복되는 구간 끝 --> </tbody> </table> {% if block_start - 1 > 0 %} <a href="{{url_for('lists', page=block_start - 1, search=search, keyword=keyword)}}">[이전]</a> {% endif %} {% for i in range(block_start, block_last + 1) %} {% if i > last_page_num %} {{ i }} {% else %} {% if i == page %} <b>{{ i }}</b> {% else %} <a href="{{url_for('lists', page=i, search=search, keyword=keyword)}}">{{ i }}</a> {% endif %} {% endif %} {% endfor %} {% if block_last < last_page_num %} <a href="{{url_for('lists', page=block_last + 1, search=search, keyword=keyword)}}">[다음]</a> {% endif %} <select name="search" id="search"> <option value="" {% if search == '' or search == -1 %} selected {% endif %}>검색대상</option> <option value="0" {% if search == 0 %} selected {% endif %}>제목</option> <option value="1" {% if search == 1 %} selected {% endif %}>내용</option> <option value="2" {% if search == 2 %} selected {% endif %}>제목+내용</option> <option value="3" {% if search == 3 %} selected {% endif %}>작성자</option> </select> <input type="text" name="keyword" id="keyword" {% if keyword != "" %} value={{keyword}} {% endif %}> <input type="button" value="검색" onclick="search()"> {% else %} <h3>데이터가 없습니다.</h3> {% endif %} <a href="{{url_for('board_write')}}">글작성</a> 오타가 있는지 문제가 될만한 부분이 있는지 5시간이나 찾아봤는데 도저히 못찾아서 문의드려봅니다. 봐주셔서 감사합니다. 버전 143.0.3650.96 (공식 빌드) (64비트) 버전 143.0.3650.96 (공식 빌드) (64비트)ㅍ

  • python
  • 몽고db검색문제
호기심고양이 댓글 1 좋아요 0 조회수 83

4주 1회차 과제

해결됨

[매일 완독 챌린지] 저자와 함께하는 <FastAPI로 기획에서 출시까지>

기획의 관점에서 Host 체크 방법 is_host 필드 체크 사용자가 호스트인지 먼저 확인을 하게 되므로 호스트 등록, 호스트만 조회, 호스트에 주어진 권한 제어 등 호스트를 따로 관리하고 싶을때 장점이 있습니다 캘린더 보유 체크 캘린더로 호스트일 경우는 호스트, 게스트 구분이 회원 등급이나 종류가 아닌 모두가 호스트나 게스트가 될수 있고 예약이 서로에게 일어날 수 있을때 장점이 있습니다. 구글 캘린더로 예를 들면 모두가 초대가 가능하고 초대도 가능한 방식입니다. 내가 선택한다면 저라면 기본적으로는 is_host 필드로 체크하고 실제 예약을 받는다면 캘린더 체크를 이후에 하겠습니다. 호스트 관리를 따로 하게 되면 호스트만 따로 조회도 가능하고 호스트를 하고 싶지 않을때는 호스트가 되지 않는 것도 가능합니다. 또한 is_host를 기본 true로 하게 되면 모두가 호스트가 되는 방식도 가능하므로 앞에서 가정한 모두가 호스트/게스트인 방식도 쉽게 전환이 가능합니다. 예약 가능한 캘린더 체크는 실제로 이사람이 호스트라고 하더라도 예약일자가 있는지에 따라 예약화면 컨트롤 등이 가능하기 때문에 체크가 필요합니다. 요약하면 is_host 체크를 할 때 상황에 따라 유연하게 호스트 <-> 게스트 전환이 쉽고 필요한 경우 호스트이면서 게스트인 정책도 가능하기 때문에 좀 더 유연한 방법이라고 생각합니다.

  • python
  • aws
  • tdd
  • FastAPI
  • 북-챌린지
김도현 댓글 2 좋아요 0 조회수 45

맥 os vscode 설정 - python interpreter select

미해결

프로그래밍 시작하기 : 파이썬 입문 (Inflearn Original)

안녕하세요. 맥 os에 vscode를 설정하려고 하는데 python interpreter select -> 알맞는 python 버전을 클릭해도 선생님과 같은 파란색 바가 안 뜨는데 어떤 문제가 있을까요? 코드를 입력해도 그에 따른 설명이 선생님과 같이 안 뜹니다(ex. 명령어 print를 입력해도 설명이 안 뜸 )

  • python
eunbee27873 댓글 1 좋아요 0 조회수 131

fal.ai 요청시 wait 보다는 status 체크가 더욱 좋을것 같아요

미해결

원클릭으로 AI가 생성해주는 Youtube 쇼츠 만들기 자동화(with n8n)

fal.ai 요청시 wait 무작정 넉넉히 잡는건 서버 메시지큐 상태를 알수없고 내 TASK가 언제 처리될지 모르는 상태에서 감(?) 으로 때리는 방법이라 엣지 케이스가 너무 많은것 같아요 주기적으로 Status 호출해서 체크하는 방법이 좋아보입니다. falai POST API 생성후 응답이 다음과 같이 오는데 status_url 을 사용하면 간단히 처리가 가능할것 같습니다. { "status": "COMPLETED", "request_id": "728614ce-f8c3-498c-8174-e4beea63b48d", "response_url": "https://queue.fal.run/fal-ai/kling-video/requests/728614ce-f8c3-498c-8174-e4beea63b48d", "status_url": "https://queue.fal.run/fal-ai/kling-video/requests/728614ce-f8c3-498c-8174-e4beea63b48d/status", "cancel_url": "https://queue.fal.run/fal-ai/kling-video/requests/728614ce-f8c3-498c-8174-e4beea63b48d/cancel", "logs": null, "metrics": { "inference_time": 41.99311113357544 } } status_url 을 다시 http request로 던지고 응답문에 switch 걸고 WAIT 상태에서 loop 돌려주면 깔끔할것 같아요 while 문처럼 내부에 sleep 있는 것 처럼 loop 돌리는게 호율적이여 보입니다. 코드 리뷰 정도의 의견이라고 생각해주세요! 강의 잘보고 있습니다. 감사합니다. 예시> 추가적으로 위에 상태조회 방법과 함께 MERGE 처리도 코드 필요없이 이렇게 구성하면 별도 code node 없이 아래처럼 가능할것 같아요! 참고 부탁드립니다. 추가1 Http auth 부분도 Header Auth 로 별도로 지정해주고 아래처럼 호출하는게 보안상 안전해 보입니다! 추가2 falai 외에도 Creatomate render post 요청 이후 응답에서 ID 조합으로 상태 체크 WAIT 를 구성하는것도 괜찮을 것 같아요! API DOCS https://creatomate.com/docs/api/reference/get-the-status-of-a-render curl -X GET https://api.creatomate.com/v2/renders/RENDER_ID \ -H "Authorization: Bearer YOUR_API_KEY_HERE" Response: { "id": "a862048b-d0dc-4029-a4ef-e172e8ded827", "status": "succeeded", "url": "https://cdn.creatomate.com/renders/a862048b-d0dc-4029-a4ef-e172e8ded827.mp4", "snapshot_url": "https://cdn.creatomate.com/snapshots/a862048b-d0dc-4029-a4ef-e172e8ded827.jpg", "output_format": "mp4", "render_scale": 1, "width": 1280, "height": 720, "frame_rate": 60, "duration": 3, "file_size": 10804 }

  • python
  • youtube-api
  • n8n
  • ai-활용-(ax)
asdf9090 댓글 3 좋아요 1 조회수 163

4주 4회차 과제 제출

미해결

[매일 완독 챌린지] 저자와 함께하는 <FastAPI로 기획에서 출시까지>

쟁점 정리 예약 일정 변경과 관련해서 결정해야 할 핵심은 다음과 같습니다: 일자/타임슬롯 변경을 허용할 것인가? vs 취소 후 재예약만 가능하게 할 것인가? 변경을 허용한다면, 언제까지 허용할 것인가? 당일 변경은 불가능하다 (이건 확정) 내가 선택한 정책 일자/타임슬롯 변경을 허용하되, 예약일 24시간 전까지만 가능 근거: "취소 → 재예약" 방식은 사용자가 불편하고, 원하는 시간이 이미 찼을 수도 있음 24시간 전까지는 게스트에게 충분한 유연성을 주면서도, 호스트가 하루 전부터 안정적으로 준비할 수 있음 규칙이 단순해서 사용자가 이해하기 쉽고, 구현도 간단함 구현 시나리오 시나리오 1: 여유 있는 변경 (성공) 민수는 2월 10일 오후 2시를 예약했습니다. 2월 7일에 2월 11일 오후 4시로 바꾸고 싶어졌습니다. → 변경 가능 (24시간 이상 여유) → "변경이 완료되었습니다." 시나리오 2: 임박한 변경 시도 (실패) 지영은 2월 10일 오후 2시를 예약했습니다. 2월 9일 오후 3시에 시간을 바꾸려고 합니다. → 변경 불가 (24시간 미만) → "예약일 24시간 전까지만 변경 가능합니다. 취소 후 재예약해주세요." 시나리오 3: 당일 변경 시도 (실패) 현우는 2월 10일 오후 2시를 예약했습니다. 2월 10일 오전 11시에 오후 4시로 바꾸려고 합니다. → 변경 불가 (당일) → "당일 일정 변경은 불가능합니다." 이상입니다.

  • python
  • aws
  • tdd
  • FastAPI
  • 북-챌린지
고리오영감 댓글 2 좋아요 0 조회수 56

4주 1회차 과제 제출합니다.

해결됨

[매일 완독 챌린지] 저자와 함께하는 <FastAPI로 기획에서 출시까지>

저는 is_host 필드와 calendar 존재 여부를 둘 다 검증해야 한다 고 판단했습니다. 왜 두 가지를 모두 사용해야 할까요? 우선 두 요소는 서로 다른 의미 를 가지고 있다고 생각합니다. is_host : 이 사용자가 호스트 자격 이 있는가? (역할) calendar 존재 : 이 호스트가 실제로 운영 중 인가? (상태) 현실로 비유하자면, is_host는 사업자등록증을 가지고 있는 상태이고, calendar가 있다는 건 실제로 가게를 오픈한 상태라고 볼 수 있습니다. 사업자등록증은 있지만 아직 가게를 열지 않은 사람도 있을 수 있잖아요? 그래서 둘 중 하나만 체크하면 문제가 생긴다고 봅니다. 만약 calendar 존재 여부만 체크한다면? calendar만 보고 판단하면 권한 체계가 무너질 수 있습니다. 예를 들어 일반 사용자가 억지로 캘린더를 생성하면 호스트로 둔갑할 수 있는 보안 문제가 생기죠. 또 호스트가 일시적으로 캘린더를 삭제했다가 다시 만들 때마다 권한 관리가 복잡해집니다. 만약 is_host만 체크한다면? 반대로 is_host만 체크하면, 캘린더가 없는데도 예약 관련 API를 호출할 수 있게 되어서 500 에러가 발생할 수 있습니다. "호스트인데 캘린더는 없는" 이상한 상태를 어떻게 처리해야 할지도 애매해지고요. 두 가지를 순차적으로 검증하는 게 좋습니다 저는 이렇게 단계적으로 확인하는 게 맞다고 봅니다: 먼저 is_host로 호스트 자격이 있는지 확인 그 다음 calendar 존재로 실제 운영 가능한지 확인 이렇게 하면 사용자에게도 명확한 피드백을 줄 수 있어요. "호스트 권한이 없습니다" vs "캘린더를 먼저 생성해주세요" 처럼 무엇을 해야 하는지 정확히 알려줄 수 있죠. 미래 확장성도 고려했습니다 나중에 서비스가 커지면 호스트 상태를 더 세분화할 수도 있을 것 같아요: 준비 중 호스트 (is_host=true, 캘린더 없음) → 대시보드 접근만 가능 운영 중 호스트 (is_host=true, 캘린더 있음) → 모든 기능 사용 가능 휴면 호스트 (is_host=true, 캘린더 비활성화) → 기존 예약 조회만 가능 이런 식으로 관리하려면 역할과 리소스를 분리해서 체크하는 게 필수라고 생각합니다. 성능 걱정은 없을까요? is_host는 User 모델의 필드라서 추가 DB 쿼리가 필요 없고, calendar 조회도 어차피 해야 하는 작업이라 성능에 큰 영향은 없다고 봅니다.

  • python
  • aws
  • tdd
  • FastAPI
  • 북-챌린지
고리오영감 댓글 1 좋아요 0 조회수 55

Linked List Element Delete Explanation Problem

해결됨

38군데 합격 비법, 2026 코딩테스트 필수 알고리즘

1. 현재 학습 진도 몇 챕터/몇 강을 수강 중이신가요? 어떤 알고리즘을 학습하고 계신가요? 여기까지 이해하신 내용은 무엇인가요? 2. 어려움을 겪는 부분 어느 부분에서 막히셨나요? 코드의 어떤 로직이 이해가 안 되시나요? 어떤 개념이 헷갈리시나요? 3. 시도해보신 내용 문제 해결을 위해 어떤 시도를 해보셨나요? 에러가 발생했다면 어떤 에러인가요? 현재 작성하신 코드를 공유해주세요 이렇게 구체적으로 알려주시면, 더 정확하고 도움이 되는 답변을 드릴 수 있습니다! 😊 아래 코드(TODO; 제가 만든 삭제코드, 정답지; 제공된 교재 답 풀이본) 에 대해 문의드립니다. 5,9,12,27 일때 정답지를 통해 결과를 뽑아보면 삭제가 안되는 현상이 일어납니다. 이와 관련해 어떻게 생각하실지 여쭙습니다! class Node: def __init__(self, data): self.data = data self.next = None class LinkedList: def __init__(self, value): self.head = Node(value) def append(self, value): cur = self.head while cur.next is not None: cur = cur.next cur.next = Node(value) def print_all(self): cur = self.head while cur is not None: print(cur.data) cur = cur.next def get_node(self, index): node = self.head count = 0 while count < index: node = node.next count += 1 return node def add_node(self, index, value): new_node = Node(value) if index == 0: new_node.next = self.head self.head = new_node return node = self.get_node(index - 1) next_node = node.next node.next = new_node new_node.next = next_node # def delete_node(self, index): # TODO # if index == 0: # 첫번째 노드를 불러와야 출력이 가능하므로 0번째 인덱스를 제거하려고하면 1번쨰 인덱스를 head로 지정 # self.head = self.head.next # return # before_node = self.get_node(index-1) # 1. 제거해야할 노드 이전 노드 찾기 # delete_node = self.get_node(index) # before_node.next = delete_node.next # 2. 이전 노드 next를 제거할 노드의 next로 # delete_node.next = None # 3. 제거할 노드의 next 를 None # return "index 번째 Node를 제거해주세요!" def delete_node(self, index): # 정답지 if index == 0: # 첫번째 노드를 불러와야 출력이 가능하므로 0번째 인덱스를 제거하려고하면 1번쨰 인덱스를 head로 지정 self.head = self.head.next return before_node = self.get_node(index-1) # 1. 제거해야할 노드 이전 노드 찾기 before_node = before_node.next.next return "index 번째 Node를 제거해주세요!" linked_list = LinkedList(5) linked_list.append(9) linked_list.append(12) linked_list.append(27) print("제거 전") linked_list.print_all() print("제거 후") linked_list.delete_node(3) linked_list.print_all()

  • python
  • 코딩-테스트
  • 알고리즘
  • data-structure
D.H Github 댓글 2 좋아요 0 조회수 89

EDIT 영상편집요청 에러

해결됨

원클릭으로 AI가 생성해주는 Youtube 쇼츠 만들기 자동화(with n8n)

사진과 같이 Bad request - please check your parameters [item 0] 400 - "{\"hint\":\"No template was found with that ID.\",\"documentation\":\" https://creatomate.com/docs/api/quick-start/introduction\ "}" 라고 뜹니다 뭐가 문제일까요 ??

  • python
  • youtube-api
  • n8n
  • ai-활용-(ax)
깜자TV 댓글 2 좋아요 0 조회수 65

수강 기한 연장 문의

미해결

[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)

안녕하세요, 강사님. 강의의 수강 기한이 곧 만료되어 문의드립니다. 최근 1년간 다른 직종에 관련된 일을 하느라 강의를 거의 수강하지 못했습니다. 이번 연도에 강의를 들으며 빅데이터분석기사 실기를 준비하고 싶은데, 혹시 수강기한을 연장해 주실 수 없을까요? 제 메일은 ksforuo@gmail.com 입니다.

  • python
  • 머신러닝
  • 빅데이터
  • pandas
  • 빅데이터분석기사
마리오 댓글 2 좋아요 0 조회수 100

4주 2회차 과제

해결됨

[매일 완독 챌린지] 저자와 함께하는 <FastAPI로 기획에서 출시까지>

안녕하세요. 과제를 잘 못 이해한건가 싶기도 하지만 아래와 같은 조건하에 구현을 해 봤습니다. 수업 과정에서 Front-end는 고정인 상황이기 때문에 기존 API는 변경이 없다는 가정하에 변경 해 봤습니다. 시간대1개와 요일n개의 설정이 하나의 row로 묶여있는 상태로는 요일별 시간대 변동에 대응하기 까다로운 것 같아 요일별 개별 row로 저장하도록 일부 수정 하였습니다. API endpoint 모델 변경을 피하기 위해서 내부적으로 여러개의 요일별 row로 나누어 저장하도록 했습니다. 고민중에 작가님께서 올려 놓으신 레퍼런스 코드를 봤는데, 책에서 언급하신 것 처럼 postgres 경우와 sqlite 경우로 코드가 분기 되는 것을 보았고, 지금은 교육 과정이기 때문이라고 생각 하지만 배포 코드와 개발 환경 코드가 다른것은 여러모로 좋지 않은 것 같아 현재는 sqlite 기준으로 개별 DB구현에서만 지원하는 것은 배제하는 방향으로 구현 했습니다. 1과 같이 변경 함으로써, 기 등록된 정보의 수정에서는 개별 날짜 별 시간대 설정 면에서 자유도가 생겼다고 생각 됩니다. 타임슬롯의 변경과 삭제에 관해서는 내부적으로는 time-slot으로 관리하지만, 외부공개 id는 아니므로, 키 로서 start-time, end-time, weekday (API형태로서는 리스트)조합으로 정의 해서 동작 하도록 구현했습니다. 특히 삭제의 경우는 부득이 delete method의 경우는 payload가 포함되는것이 받아들여지지 않는 경우도 있는것을 고려해서, 새 등록 값 두가지(new_start_time과, new_end_time) 값이 모두 제공되고 같은 경우를 특정하여 삭제 동작으로 정의하여 동작하도록 구현했습니다. class TimeSlotUpdateByGroupIn(SQLModel): start_time: time end_time: time weekdays: Weekdays new_start_time: time | None = None new_end_time: time | None = None new_weekdays: Weekdays | None = None @model_validator(mode="after") def check_update_fields(self): update_fields = { "new_start_time": self.new_start_time, "new_end_time": self.new_end_time, "new_weekdays": self.new_weekdays, } if not any(value is not None for value in update_fields.values()): raise ValueError("최소 하나의 수정 필드는 반드시 제공되어야 합니다.") return self @router.post("/time-slots", status_code=status.HTTP_201_CREATED, response_model=TimeSlotOut) async def create_time_slot( user: CurrentUserDep, session: DbSessionDep, payload: TimeSlotCreateIn, ) -> TimeSlotOut: if not user.is_host: raise GuestPermissionError() weekdays = sorted(set(payload.weekdays)) # dup. check with already exist one stmt = select(TimeSlot).where( and_( TimeSlot.calendar_id == user.calendar.id, TimeSlot.weekday.in_(weekdays), TimeSlot.start_time < payload.end_time, TimeSlot.end_time > payload.start_time, ) ) result = await session.execute(stmt) existing_time_slot = result.scalars().first() if existing_time_slot: raise TimeSlotOverlapError() time_slots = [ TimeSlot( calendar_id=user.calendar.id, start_time=payload.start_time, end_time=payload.end_time, weekday=weekday, ) for weekday in weekdays ] session.add_all(time_slots) await session.commit() if not time_slots: raise TimeSlotOverlapError() return TimeSlotOut( start_time=time_slots[0].start_time, end_time=time_slots[0].end_time, weekdays=weekdays, created_at=time_slots[0].created_at, updated_at=time_slots[0].updated_at, ) @router.get( "/time-slots/{host_username}", status_code=status.HTTP_200_OK, response_model=list[TimeSlotOut], ) async def get_host_timeslots( host_username: str, session: DbSessionDep, ) -> list[TimeSlotOut]: stmt = ( select(User) .where(User.username == host_username) .where(User.is_host.is_(true())) ) result = await session.execute(stmt) host = result.scalar_one_or_none() if host is None or host.calendar is None: raise HostNotFoundError() stmt = select(TimeSlot).where(TimeSlot.calendar_id == host.calendar.id) result = await session.execute(stmt) time_slots = result.scalars().all() grouped: dict[tuple[time, time], TimeSlotOut] = {} for time_slot in time_slots: key = (time_slot.start_time, time_slot.end_time) if key not in grouped: grouped[key] = TimeSlotOut( start_time=time_slot.start_time, end_time=time_slot.end_time, weekdays=[time_slot.weekday], created_at=time_slot.created_at, updated_at=time_slot.updated_at, ) continue grouped[key].weekdays.append(time_slot.weekday) if time_slot.created_at < grouped[key].created_at: grouped[key].created_at = time_slot.created_at if time_slot.updated_at > grouped[key].updated_at: grouped[key].updated_at = time_slot.updated_at if not grouped: raise TimeSlotNotFoundError() for time_slot in grouped.values(): time_slot.weekdays = sorted(set(time_slot.weekdays)) return list(grouped.values()) @router.patch( "/time-slots", status_code=status.HTTP_200_OK, response_model=TimeSlotOut | None, ) async def update_time_slot( user: CurrentUserDep, session: DbSessionDep, payload: TimeSlotUpdateByGroupIn, ) -> TimeSlotOut | None: if not user.is_host: raise GuestPermissionError() current_weekdays = sorted(set(payload.weekdays)) stmt = select(TimeSlot).where( and_( TimeSlot.calendar_id == user.calendar.id, TimeSlot.start_time == payload.start_time, TimeSlot.end_time == payload.end_time, ) ) result = await session.execute(stmt) current_slots = result.scalars().all() if not current_slots: raise TimeSlotNotFoundError() existing_weekdays = sorted({slot.weekday for slot in current_slots}) if existing_weekdays != current_weekdays: raise TimeSlotNotFoundError() delete_only = ( payload.new_start_time is not None and payload.new_end_time is not None and payload.new_start_time == payload.new_end_time ) if delete_only: current_ids = [slot.id for slot in current_slots] await session.execute(delete(TimeSlot).where(TimeSlot.id.in_(current_ids))) await session.commit() return None new_start_time = payload.new_start_time or payload.start_time new_end_time = payload.new_end_time or payload.end_time new_weekdays = sorted(set(payload.new_weekdays or payload.weekdays)) if new_start_time >= new_end_time: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_CONTENT, detail="시작 시간은 종료 시간보다 빨라야 합니다.", ) current_ids = [slot.id for slot in current_slots] stmt = select(TimeSlot).where( and_( TimeSlot.calendar_id == user.calendar.id, TimeSlot.weekday.in_(new_weekdays), TimeSlot.start_time < new_end_time, TimeSlot.end_time > new_start_time, TimeSlot.id.not_in(current_ids), ) ) result = await session.execute(stmt) existing_time_slot = result.scalars().first() if existing_time_slot: raise TimeSlotOverlapError() await session.execute(delete(TimeSlot).where(TimeSlot.id.in_(current_ids))) new_time_slots = [ TimeSlot( calendar_id=user.calendar.id, start_time=new_start_time, end_time=new_end_time, weekday=weekday, ) for weekday in new_weekdays ] session.add_all(new_time_slots) await session.commit() return TimeSlotOut( start_time=new_start_time, end_time=new_end_time, weekdays=new_weekdays, created_at=new_time_slots[0].created_at, updated_at=new_time_slots[0].updated_at, )

  • python
  • aws
  • tdd
  • FastAPI
  • 북-챌린지
Green Lee 댓글 1 좋아요 0 조회수 65

IMG - JSON 병 및 ID추가에서 ID가 추가가 안됩니다.

해결됨

원클릭으로 AI가 생성해주는 Youtube 쇼츠 만들기 자동화(with n8n)

merged["ID"] = _('IMG - 시트 행 가져오기').first(). json.ID 이부분에서 = 뒤로 지우고 IMG 시트 행 가져오기에서 ID를 드래그엔 드롭했을때 강사님처럼 아이디가 입력이 안되는데 이유가 뭘까요? 일단은 복사 붙여넣기로 진행했는데 궁금해서 질문 남깁니다.

  • python
  • youtube-api
  • n8n
  • ai-활용-(ax)
적성비 댓글 2 좋아요 0 조회수 76

저는 왜 그대로 했는데 답변이 틀리게 나오는지 모르겠네요

미해결

RAG를 활용한 LLM Application 개발 (feat. LangChain)

소득세법 제55조(세율) 및 제47조(근로소득공제)에 따르면, 거주자 기준으로 연봉 5천만원(근로소득)의 소득세는 다음과 같이 계산됩니다. 근로소득공제 적용 총급여액 5천만원 기준 공제액: 1,475만원 (5천만원 × 15% + 75만원, 단 최고 한도 2천만원 미만) 과세표준 산정 5천만원 - 1,475만원 = 3,525만원 종합소득세율 적용 3,525만원 구간: 1,400만원 이하 6% + 초과분 15% 산출세액: 84만원(1,400만원 × 6%) + (3,525만원 - 1,400만원) × 15% = 474.75만원 최종 납부세액 474.75만원에서 근로소득세액공제 (산출세액의 55% 한도) 등 추가 공제 적용 가능 ※ 정확한 세액은 의료비·교육비·보험료 등 추가 공제항목에 따라 달라질 수 있습니다. (추가 설명: "거주자"는 직장·자영업 등 소득 유형과 무관하게 국적에 관계없이 국내 주소를 둔 개인을 의미하며, 직장인은 그 하위 범주에 포함됩니다.) 답변이 전혀 다르고 이상하게 근거없는 숫자도 나오는데 왜그런걸까유 fewshot하는것까지 작성했습니다.

  • vector-database
  • llm
  • langchain
  • rag
  • openai-api
guri Mag 댓글 2 좋아요 0 조회수 133

강의 보다가 궁금한점 남깁니다.

해결됨

100% 비개발자 바이브 코딩: 앱 200개로 월 140만 수익 노하우

안녕하세요. 좋은 강의 감사합니다. 강의를 듣다 몇가지 의문이 있어 글을 작성합니다. 애드몹 광고는 비공개 테스트시에도 적용을 해야하나요. 비공개 테스트시에도 애드몹광고를 추가한 상태에서 진행해야하나요? 비공개 테스트가 완료된 상태에서 애드몹광고를 추가하고 출시가 가능한가요? 비공개 테스트시에는 애드몸광고를 넣지않고 앱을 개시할때 추가해도되나요 애드몹 공고로 등록한 모바일 폰은 비공개 테스트 시 12개중한개의 모바일폰에 포함되나요.

  • python
  • flutter
  • chatgpt
  • claude
  • 바이브코딩
이승섭 댓글 1 좋아요 2 조회수 142

patch 요청시 payload가 넘어가지 않습니다.

해결됨

[매일 완독 챌린지] 저자와 함께하는 <FastAPI로 기획에서 출시까지>

아래 두 요청 코드에서 patch 요청 시 payload가 엔드포인트 함수에서 None으로 잡혀 model_dump()에서 오류가 발생합니다. 원인을 잘 모르겠습니다. [오류] [요청 코드] @pytest.mark.parametrize("payload", [ {"display_name": "푸딩캠프"}, {"email": "hannal@example.com"}, {"display_name": "푸딩캠프", "email": "hannal@example.com"}, ]) async def test_사용자가_변경하는_항목만_변경되고_나머지는_기존_값을_유지한다( client_with_auth: TestClient, # 인증을 받은 클라이언트 payload: dict, # 클라이언트 요청 페이로드 host_user: User, # 클라이언트 사용자 ): # 현재 사용자 정보를 보관한다. before_data = host_user.model_dump() response = client_with_auth.patch("/account/@me", json=payload) # (...) async def test_비밀번호_변경_시_해싱_처리한_비밀번호가_저장되어야_한다( client_with_auth: TestClient, host_user: User, db_session: AsyncSession, ): before_data = host_user.hashed_password payload = { "password": "new_password", "password_again": "new_password", } response = client_with_auth.patch("/account/@me", json=payload) # (...) [엔드포인트] @router.patch("/@me", response_model=UserDetailOut) async def update_user( user: CurrentUserDep, session: DbSessionDep, payload: UpdateUserPayload = Body(...), ) -> User: updated_data = payload.model_dump(exclude_none=True, exclude={"password", "password_again"}) stmt = update(User).where(User.id == user.id).values(**updated_data) await session.execute(stmt) await session.commit() await session.refresh(user) return user [스키마] class UpdateUserPayload(SQLModel): display_name: str | None = Field(default=None, min_length=4, max_length=40) email: EmailStr | None = Field(default=None, max_length=128) password: str | None = Field(default=None, min_length=8, max_length=128) password_again: str | None = Field(default=None, min_length=8, max_length=128) @model_validator(mode="after") def check_all_fields_are_none(self) -> Self: if not self.model_dump(exclude_none=True): raise ValueError("최소 하나의 필드는 반드시 제공되어야 합니다.") return self @model_validator(mode="after") def verify_password(self) -> Self: if self.password is not None or self.password_again is not None: # 둘 중 하나라도 들어오면 둘 다 있어야 함 if not self.password or not self.password_again: raise ValueError("비밀번호 변경 시 password와 password_again을 모두 제공해야 합니다.") if self.password != self.password_again: raise ValueError("비밀번호가 일치하지 않습니다.") @computed_field @property def hashed_password(self) -> str | None: if self.password: return hash_password(self.password) return None [픽스처] @pytest.fixture(autouse=True) async def db_session(): dsn = "sqlite+aiosqlite:///:memory:" engine = create_async_engine(dsn) async with engine.begin() as conn: await conn.run_sync(SQLModel.metadata.drop_all) await conn.run_sync(SQLModel.metadata.create_all) session_factory = create_session(engine) async with session_factory() as session: yield session await conn.run_sync(SQLModel.metadata.drop_all) await engine.dispose() @pytest.fixture() def fastapi_app(db_session: AsyncSession): app = FastAPI() include_routers(app) async def override_use_session(): yield db_session app.dependency_overrides[use_session] = override_use_session return app @pytest.fixture() async def host_user(db_session: AsyncSession): user = account_models.User( username="puddingcamp", hashed_password=hash_password("testtest"), email="puddingcamp@example.com", display_name="푸딩캠프", is_host=True, ) db_session.add(user) await db_session.flush() await db_session.commit() return user @pytest.fixture() def client_with_auth(fastapi_app: FastAPI, host_user: account_models.User): payload = LoginPayload.model_validate({ "username": host_user.username, "password": "testtest", }) with TestClient(fastapi_app) as client: response = client.post("/account/login", json=payload.model_dump()) assert response.status_code == status.HTTP_200_OK auth_token = response.cookies.get("auth_token") assert auth_token is not None client.cookies.set("auth_token", auth_token) yield client

  • python
  • aws
  • tdd
  • FastAPI
  • 북-챌린지
kyo lee 댓글 3 좋아요 0 조회수 79

run pod credit 관련 제보

미해결

[개정판] 딥러닝 컴퓨터 비전 완벽 가이드

저는 강사님의 refer & earn 주소로 runpod.io 사이트 열고, 영상에 나온 팝업창 누르고 구글 계정으로가입하고 10달러 결제까진 순조롭게 되었습니다....만 5달러는 안들어왔고 딱 결제한만큼 10달러만 있네요! 다른 분들은 어떻게... 추가로 5달러 받으셨는지 궁금합니다.

  • python
  • 머신러닝
  • 딥러닝
  • 컴퓨터-비전
limtony1 댓글 2 좋아요 0 조회수 155

강의 순서

해결됨

코딩 테스트 합격을 위한 리트코드 핵심 문제 풀이

강의 수강 방법에 대해서 질문이 있습니다. 저는 Blind75를 순서대로 풀고 있는데 강의 순서랑은 Blind75 순서랑 조금 다르더라구요 자료구조 알고리즘을 모르는 상태로 강의를 시작해도 되는지 1번과 연계되는 질문으로 일단 문제 풀이를 시도하되 한 문제당 어느정도의 시간을 두고 풀면 되는지 보통 10분 정도 고민해보고 정말 모르겠다면 문제풀이 강의를 바로 들어보는 편입니다. Blind75 순서대로 문제를 풀면서 풀지 못한 문제에 대해서만 강의를 시청하면 되는지 좋은 강의 만들어주셔서 감사합니다.

  • python
  • 코딩-테스트
  • 알고리즘
  • data-structure
shin jiun 댓글 1 좋아요 1 조회수 149

langchain howto/sequence는 지금 doc 공식 사이트 어디서 확인할 수 있나요?

미해결

RAG를 활용한 LLM Application 개발 (feat. LangChain)

| 이런 파이프라인 문법 수업중에 보이는 how-to-guides의 링크가 어디인가요? 공식문서가 많이 업데이트 되었는지 수업 전반으로 일치하는 부분 찾기가 너무 힘드네요...

  • vector-database
  • llm
  • langchain
  • rag
  • openai-api
Jeong-ah Yoon 댓글 1 좋아요 1 조회수 120

new_question에 대한 답 출력

해결됨

RAG를 활용한 LLM Application 개발 (feat. LangChain)

new_question 이 ''연봉 5천만원인 거주자의 소득세는 얼마인가요?'' 이라는 질문만 내놓고, 답은 내놓지 않습니다 %pip install python-dotenv langchain langchain-upstage langchain-community langchain-text-splitters langchain-pinecone docx2txt from langchain_community.document_loaders import Docx2txtLoader from langchain_text_splitters import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=1500, chunk_overlap=200, ) loader = Docx2txtLoader('./tax.docx') document_list = loader.load_and_split(text_splitter=text_splitter) from dotenv import load_dotenv from langchain_upstage import UpstageEmbeddings # 환경변수를 불러옴 load_dotenv() # OpenAI에서 제공하는 Embedding Model을 활용해서 `chunk`를 vector화 embedding = UpstageEmbeddings(model="embedding-query") from langchain_pinecone import PineconeVectorStore # 데이터를 처음 저장할 때 index_name = 'tax-upstage-index' database = PineconeVectorStore.from_documents(document_list, embeddin g, index_name=index_name) query = '연봉 5천만원인 직장인의 소득세는 얼마인가요?' # `k` 값을 조절해서 얼마나 많은 데이터를 불러올지 결정 retrieved_docs = database.similarity_search(query, k=3) retrieved_docs from langchain_upstage import ChatUpstage llm = ChatUpstage() from langchain_core.prompts import PromptTemplate prompt_with_template = '아래 질문에 답변해주세요:\n\n {query}' prompt_template = PromptTemplate(template=prompt_with_template, input_variables={"query"}) from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate dictionary = ["사람을 나타내는 표현 -> 거주자"] prompt = ChatPromptTemplate.from_template(f""" 사용자의 질문을 보고, 우리의 사전을 참고해서 사용자의 질문을 변경해주세요. 만약 변경할 필요가 없다고 판단된다면, 사용자의 질문을 변경하지 않아도 됩니다. 그런 경우에는 질문만 리턴해주세요 사전: {dictionary} 질문: {{question}} """) dictionary_chain = prompt | llm | StrOutputParser() tax_chain = {"query": dictionary_chain} | prompt_template new_question = dictionary_chain.invoke({"question": query}) new_question RetrievalQA 가 사라져서 PromptTemplate 랑 Pinecorn으로 어떻게든 대체하려고 했는데 엉망이 된거 같습니다. ㅠㅠ 어떻게 하면 답까지 내놓게 할 수 있을까요?

  • vector-database
  • llm
  • langchain
  • rag
  • openai-api
다화 (만점) 댓글 2 좋아요 0 조회수 97

인기 태그

인프런 TOP Writers

주간 인기글