Django 개인프로젝트/첫번째 프로젝트

7. html 템플릿 Django프로젝트 (1)

수달1234 2024. 11. 5. 14:18

0. 서론

팀 프로젝트에서는 APIView를 사용해 백엔드를 구현하면, 프론트엔드 담당 팀원들이 나머지 작업을 이어받아 개발을 완성할 수 있었습니다. 그러나 개인 프로젝트에서는 백엔드만으로 프로젝트 결과물을 효과적으로 보여주기 어려움을 느꼈습니다. 그래서 HTML 템플릿을 사용하여 내가 구현한 기능을 직접 시각화하기로 결정했습니다. 물론, 기본적인 기능만 보여줄수있도록... 

 

 

1. 로그인 뷰

class LoginView(View):
    def get(self, request):
        return render(request, 'users/login.html')

    def post(self, request):
        # 폼에서 전송된 데이터 가져오기
        email = request.POST.get('email')
        password = request.POST.get('password')

        # 유저 인증
        user = authenticate(email=email, password=password)

        if user is not None:
            # JWT 토큰 생성
            token = TokenObtainPairSerializer.get_token(user)
            refresh_token = str(token)
            access_token = str(token.access_token)

            # 응답 생성
            res = redirect('post-list-create')  # 로그인 후 리디렉션할 페이지
            res.set_cookie("access", access_token, httponly=True)
            res.set_cookie("refresh", refresh_token, httponly=True)

            # 성공 메시지 추가 (선택 사항)
            messages.success(request, '로그인에 성공하였습니다.')

            return res
        else:
            # 에러 메시지 추가 (선택 사항)
            messages.error(request, '이메일 또는 비밀번호가 올바르지 않습니다.')
            return render(request, 'users/login.html')
            
            
            
class LogoutView(View):
    def post(self, request):
        response = redirect('post-list-create')
        response.delete_cookie('access')
        response.delete_cookie('refresh')
        messages.success(request, '로그아웃되었습니다.')
        return response

(1) get 요청이 들어올때 지정된 로그인 페이지를 보여주도록 합니다.

(2) post 요청이 들어올때 사용자가 제출한 (request.Post.get()) 폼 데이터에서 email과 password를 가져옵니다.

(3) 장고 함수 authenticate()를 사용해서 이메일과 패스워드를 인증합니다. 성공하면 user 객체를 반환하고 실패시 none을 반환합니다.

(4) 인증 성공 시   TokenObtainPairSerializer을 사용해 jwt토큰을 생성합니다. refresh와 access토큰을 받습니다.

(5) 로그인을 한다면 'post-list-create'라는 이름을 가진 페이지로 리디렉션하도록합니다.

(후에 추가할예정)

(6) 각각의 토큰을 쿠키에 저장합니다. 그 후 메세지를 출력하고 응답을 반환합니다.

(7) 실패시 다시 로그인창을 반환하도록 합니다.

(8) 로그아웃 뷰를 통해 post요청이 들어오면 로그아웃 처리를 수행하도록합니다.

(9) 지정된 페이지로 리디렉션하는 객체를 생성하고 각각의 토큰을 삭제합니다.

(10) 후에 응답을 클라이언트로 전달될 때 쿠키가 삭제된 상태로 리디렉션이 실행됩니다.

* 로그아웃 기능은 후에 구현될 예정

 

 

 

2. 회원가입 뷰

class SignupView(View):
    def get(self, request):
        return render(request, 'users/signup.html')

    def post(self, request):
        # 폼에서 전송된 데이터 가져오기
        email = request.POST.get('email')
        nickname = request.POST.get('nickname') 
        password = request.POST.get('password')
        password2 = request.POST.get('password2')

        if password != password2:
            messages.error(request, '비밀번호가 일치하지 않습니다.')
            return render(request, 'users/signup.html')

        # 유저 데이터 준비
        user_data = {
            'email': email,
            'nickname': nickname,
            'password': password
        }

        # UserSerializer를 사용해 유저 생성
        serializer = UserSerializer(data=user_data)
        if serializer.is_valid():
            user = serializer.save()

            messages.success(request, '회원가입에 성공하였습니다.')
            return redirect('login')  # 회원가입 후 로그인 페이지로 리디렉션
        else:
            # 유효성 검사 오류 출력
            print("Validation errors:", serializer.errors)
            messages.error(request, '회원가입에 실패하였습니다.')
            return render(request, 'users/signup.html', {'errors': serializer.errors})

(1) get요청이 들어오면 해당 페이지를 랜더링 합니다.

(2) post요청이 오면 사용자가 작성한 폼 데이터를 가져옵니다(request.POST.get)

(3) 비밀번호 확인란을 추가해 같은 비밀번호가 아니면 다시 처음으로 되돌아갑니다.

(4) 입력받은 유저정보를 딕셔너리 형태로 UserSerializer에 전달하도록 합니다.

(5) 전달 받은 데이터가 유효하면 새로운 사용자 객체를 생성하고 저장합니다.

 

3.users/urls.py

from django.urls import path
from users import views

urlpatterns = [
    ## api
    path('signupAPI/', views.SignupAPIView.as_view()),
    path('auth/', views.AuthApiView.as_view()),
    
    
    ## html
    path('signup/', views.SignupView.as_view(),name='signup'),
    path('login/', views.LoginView.as_view(), name='login'),
    path('logout/', views.LogoutView.as_view(), name='logout'),
]

# 이전에 작성해둔 apiView를 냅두고 새롭게 추가했습니다.

 

4. users/templates/users 

html을 보여줄라면 새롭게 폴더를 생성해야합니다

4-1) login.html

 

<html>
<head>
    <title>로그인</title>
</head>
<body>
    <h1>로그인</h1>
    <form method="post">
        {% csrf_token %}
        <label for="email">이메일:</label>
        <input type="email" name="email" id="email" required><br><br>
        <label for="password">비밀번호:</label>
        <input type="password" name="password" id="password" required><br><br>
        <button type="submit">로그인</button>
    </form>
    <p>계정이 없으신가요? <a href="{% url 'signup' %}">회원가입</a></p>
</body>
</html>

# 간단하게 기능만 구현하였습니다.

# 결과

4-2) signup.html

<!DOCTYPE html>
<html>
<head>
    <title>회원가입</title>
</head>
<body>
    <h1>회원가입</h1>
    <form method="post">
        {% csrf_token %}
        <label for="email">이메일:</label>
        <input type="email" name="email" id="email" required><br><br>

        <label for="nickname">닉네임:</label>  <!-- 닉네임 필드 추가 -->
        <input type="text" name="nickname" id="nickname" required><br><br>

        <label for="password">비밀번호:</label>
        <input type="password" name="password" id="password" required><br><br>

        <label for="password2">비밀번호 확인:</label>
        <input type="password" name="password2" id="password2" required><br><br>

        <button type="submit">회원가입</button>
    </form>
    <p>이미 계정이 있으신가요? <a href="{% url 'login' %}">로그인</a></p>
</

 

# 로그인 창에 회원가입 버튼을 누르면 나오도록 구현했습니다.

# 결과

 

# db.sqlite3 폴더 확인한 결과 제대로 생성되었고 비밀번호도 잘 해싱 되었을음 확인하였습니다.

 

 

 

5. 후기

아직 부족한것이 많습니다. 후에 늘려나가야할 구현 목록

1. 닉네임, 이메일 중복시 사용자에게도 에러 메세지를 보내도록 구현

2. 회원가입시 이미지도 입력하도록 구현(필수는 x)

3. 마이페이지 창 구현(본인 정보 수정 등등)

4. 게시글 작성

등등등