심리테스트 routes.py 코드분석 2

김재원·2024년 10월 18일
  1. 기본 페이지 관리
    1.1 홈 페이지 렌더링
    기능: 사용자에게 기본 입력 페이지(index.html)를 렌더링합니다.
    경로: "/"
    메서드: GET
@main.route("/", methods=["GET"])
def home():
    return render_template("index.html")

1.2 참여자 추가
기능: JSON으로 전달된 데이터를 받아 Participant 객체를 생성하고, 데이터베이스에 추가합니다.
또한, 성공적으로 추가 후에는 리다이렉션 URL과 참가자 ID를 반환합니다.
경로: "/participants"
메서드: POST

@main.route("/participants", methods=["POST"])
def add_participant():
    data = request.get_json()
    new_participant = Participant(
        name=data["name"], age=data["age"], gender=data["gender"], created_at=datetime.utcnow()
    )
    db.session.add(new_participant)
    db.session.commit()

    return jsonify({"redirect": url_for("main.quiz"), "participant_id": new_participant.id})
  1. 퀴즈 관리
    2.1 퀴즈 페이지 렌더링
    기능: 참가자 ID가 쿠키에 있는지 확인하고, 퀴즈 페이지(quiz.html)를 렌더링합니다. 참가자 ID가 없으면 홈으로 리다이렉트합니다.
    경로: "/quiz"
    메서드: GET
@main.route("/quiz")
def quiz():
    participant_id = request.cookies.get("participant_id")
    if not participant_id:
        return redirect(url_for("main.home"))

    questions = Question.query.all()
    questions_list = [question.content for question in questions]
    return render_template("quiz.html", questions=questions_list)

2.2 퀴즈 제출
기능: 퀴즈 응답을 JSON으로 받아, 데이터베이스에 Quiz 객체로 저장합니다. 참가자 ID가 없으면 에러를 반환합니다.
경로: "/submit"
메서드: POST

@main.route("/submit", methods=["POST"])
def submit():
    participant_id = request.cookies.get("participant_id")
    if not participant_id:
        return jsonify({"error": "Participant ID not found"}), 400

    data = request.json
    quizzes = data.get("quizzes", [])

    for quiz in quizzes:
        new_quiz_entry = Quiz(
            participant_id=participant_id,
            question_id=quiz.get("question_id"),
            chosen_answer=quiz.get("chosen_answer"),
        )
        db.session.add(new_quiz_entry)

    db.session.commit()
    return jsonify({"message": "Quiz answers submitted successfully.", "redirect": url_for("main.show_results")})

  1. 질문 관리
    3.1 질문 목록 가져오기
    기능: is_active가 True인 질문만 가져와 order_num에 따라 정렬된 JSON 목록을 반환합니다.
    경로: "/questions"
    메서드: GET
@main.route("/questions")
def get_questions():
    questions = (
        Question.query.filter(Question.is_active == True)
        .order_by(Question.order_num)
        .all()
    )
    questions_list = [
        {"id": question.id, "content": question.content, "order_num": question.order_num}
        for question in questions
    ]
    return jsonify(questions=questions_list)
  1. 결과 및 시각화
    4.1 퀴즈 결과 시각화 및 결과 페이지 렌더링
    기능: 참가자 및 퀴즈 데이터를 pandas DataFrame으로 변환하고, Plotly를 사용해 다양한 통계 그래프를 생성한 뒤, 이를 JSON으로 변환하여 결과 페이지(results.html)에 전달합니다.
    경로: "/results"
    메서드: GET
@main.route("/results")
def show_results():
    participants_query = Participant.query.all()
    quizzes_query = Quiz.query.join(Question).all()

    # 참가자 및 퀴즈 데이터를 DataFrame으로 변환
    participants_df = pd.DataFrame([{"age": p.age, "gender": p.gender} for p in participants_query])
    quizzes_df = pd.DataFrame([
        {"question_id": q.question_id, "chosen_answer": q.chosen_answer, "participant_age": q.participant.age}
        for q in quizzes_query
    ])

    # Plotly 그래프 생성 (예: 나이/성별 분포 및 질문 응답 히스토그램)
    fig_age = px.pie(participants_df, names="age", hole=0.3, title="Age Distribution", ...)
    fig_gender = px.pie(participants_df, names="gender", hole=0.3, title="Gender Distribution", ...)
    
    # JSON 변환 및 렌더링
    graphs_json = json.dumps({"age_distribution": fig_age, "gender_distribution": fig_gender}, cls=plotly.utils.PlotlyJSONEncoder)
    return render_template("results.html", graphs_json=graphs_json)
  1. 관리자 페이지
    5.1 관리자 로그인
    기능: 관리자는 사용자명과 비밀번호를 입력하여 로그인할 수 있습니다. 올바르게 로그인되면 관리자 세션을 설정하고 대시보드로 리다이렉트됩니다.
    경로: "/admin/"
    메서드: GET, POST
@admin.route("", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username = request.form["username"]
        password = request.form["password"]
        admin = Admin.query.filter_by(username=username).first()

        if admin and check_password_hash(admin.password, password):
            session["admin_logged_in"] = True
            return redirect(url_for("admin.dashboard"))
        else:
            flash("Invalid username or password")

    return render_template("admin.html")

5.2 관리자 로그아웃
기능: 관리자가 로그아웃할 때 세션에서 로그인 정보를 제거하고 로그인 페이지로 리다이렉트합니다.
경로: "/admin/logout"
메서드: GET

@admin.route("/logout")
def logout():
    session.pop("admin_logged_in", None)
    return redirect(url_for("admin.login"))

5.3 대시보드
기능: 관리자 대시보드에서 날짜별 참가자 수를 그래프로 표시합니다.
경로: "/admin/dashboard"
메서드: GET
데코레이터: @login_required (로그인 여부 확인)

@admin.route("/dashboard")
@login_required
def dashboard():
    participant_counts = (
        db.session.query(func.date(Participant.created_at).label("date"), func.count(Participant.id).label("count"))
        .group_by("date")
        .all()
    )
    graph = go.Figure(go.Scatter(x=[r.date for r in participant_counts], y=[r.count for r in participant_counts], mode="lines+markers"))
    graph.update_layout(title="일자별 참가자 수", xaxis_title="날짜", yaxis_title="참가자 수")
    graph_div = plot(graph, output_type="div", include_plotlyjs=False, config={'displayModeBar': False})
    return render_template("dashboard.html", graph_div=graph_div)

5.4 질문 관리
기능: 관리자는 새로운 질문을 추가하거나 기존 질문을 수정할 수 있으며, 질문의 활성화 여부(is_active)도 설정 가능합니다.
경로: "/admin/dashboard/question"
메서드: GET, POST
데코레이터: @login_required (로그인 여부 확인)

@admin.route("/dashboard/question", methods=["GET", "POST"])
@login_required
def manage_questions():
    if request.method == "POST":
        if "new_question" in request.form:
            new_question = Question(
                content=request.form["content"], order_num=request.form["order_num"], is_active=("is_active" in request.form)
            )
            db.session.add(new_question)
            db.session.commit()
        else:
            question = Question.query.get(request.form["question_id"])
            if question:
                question.content = request.form["content"]
                question.order_num = request.form["order_num"]
                question.is_active = "is_active" in request.form
                db.session.commit()

    questions = Question.query.order_by(Question.order_num).all()
    return render_template("manage_questions.html", questions=questions)
profile
내가 부족하지 않습니다

0개의 댓글