ViewSet에 Custom Method 만들기

김의석 ·2025년 1월 20일

Hello! Poko Ver.2

목록 보기
23/28

ViewSet에 Custom Method 만들기

문제

  • 문제 요약: React의 CreateStudentModal에서 사용할 “담당 선생님 리스트”를 제공하는 API를 Django의 ViewSet의 Custom Method를 통해 구현한다.

  • 오류 메시지: 없음

문제 해결 과정

1. 기존 사용 viewset

class TeachersViewSet(ViewSet):
    serializer_class = TeacherSerializer
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTCookieAuthentication]

    def list(self, request):
        user = request.user
        if user.is_authenticated:
            teacher_name = user.full_name  

        else:
            teacher_name = "Failed Authentication"  # 로그인되지 않은 경우 처리
        return Response({"teacher_name": teacher_name})

출석부 화면에 현재 로그인 유저(선생님)의 이름만 표시하기위해 로그인 유저의 {"teacher_name": teacher_name}를 Response 한다.

2. 기존 viewset에 Custom Method 추가

@action(detail=False, methods=["get"], url_path="all-teachers")
    def get_all_teachers(self, request):
        teachers = CustomUser.objects.values("id", "full_name")  # 필요한 필드만 가져오기
        teacher_names = [
            {"id": teacher["id"], "name": teacher["full_name"]} for teacher in teachers
        ]
        return Response(teacher_names)

신규 학생 등록시 관리자가 담당선생님을 지정할 수 있게 모든 유저의 이름을 가져와 명단으로 출력한다.

  • @action : DFR의 데코레이터, ViewSet에 사용자 정의 엔드포인트를 추가한다.
  • detail=False : 리스트 엔드포인트로 동작하며, 특정 객체가 아닌 전체 데이터를 처리한다.
  • methods=["get"] : HTTP GET 메서드로만 호출할 수 있다.
  • url_path=“all-teachers” : API의 엔드포인트를 명시적으로 지정한다.
teachers = CustomUser.objects.values("id", "full_name")  # 필요한 필드만 가져오기
        teacher_names = [
            {"id": teacher["id"], "name": teacher["full_name"]} for teacher in teachers
        ]
  • .values : 전체 객체를 가져오지 않고 .values를 통해 필요한 필드만 가져오게한다.

  • 리스트 컴프리핸션을 통해 데이터 구조를 알맞게 수정한다.

3. React Modal에서 Response 데이터를 사용.

useEffect

useEffect(() => {
        const getAllTeachers = async () => {
            try {
                const data = await fetchAllTeachers();
                setTeachers(data); 
            } catch (error) {
                console.error("Error fetching all teachers:", error);
                setTeachers([]);
            }
        };
        getAllTeachers();
    }, []);
  • 컴포넌트가 처음 렌더링될 때 getAllTeachers 함수는
    fetchAllTeachers API를 통해 선생님 데이터를 가져온다.

  • 성공적으로 데이터를 가져오는 경우 setTeachers(data)를 호출하여 teachers의 상태를 업데이트한다.

  • 실패하는 경우 오류 메세지와 함께 teachers 상태를 빈배열로 초기화한다.

form

<Form.Item
  label="담당 선생님"
  name="teacher"
  rules={[{ required: true, message: "담당 선생님을 선택해주세요!" }]}
  >
    <Select placeholder="선생님 선택">
      {teachers.length > 0
       ? teachers.map((teacher) => (
         <Option key={teacher.id} value={teacher.id}>
         {teacher.name}
  </Option>
  ))
  : <Option disabled>선생님 없음</Option>}
  </Select>
</Form.Item>

<Form.Item>의 역할

  • name="teacher": 선택된 값이 폼의 teacher 필드에 저장된다.
  • rules: 유효성 검사를 설정한다.
  • required: true: 폼이 제출되기 전에 값이 반드시 입력되어야 한다.
  • 값이 입력되지 않으면 "담당 선생님을 선택해주세요!" 메시지가 표시된다.

Select와 teachers 상태

  • teachers 상태는 useEffect를 통해 업데이트된다.
  • teachers.length > 0 조건 : teachers 배열에 데이터가 있으면 map을 통해 각 항목을 Option으로 렌더링합니다. 각 Option은 teacher.id를 value로, teacher.name을 텍스트로 표시합니다.
  • teachers.length === 0 조건: teachers가 빈 배열이면 에 “선생님 없음”을 표시합니다.
profile
널리 이롭게

0개의 댓글