22.Django(장고) - ecommerce 프로젝트 - 로그인과 로그아웃

JungSik Heo·2024년 12월 6일
post-thumbnail

1.로그인 기능

여러 사람이 사용하는 질문 답변 게시판이다. 하지만 현재까지 파이보에는 회원가입 기능도 로그인, 로그아웃 기능도 없었다. 질문을 올린 사람, 답변을 올린 사람을 구별하기 위해서는 로그인과 로그아웃 기능이 필수이다.

장고의 로그인, 로그아웃을 도와주는 앱은 django.contrib.auth 이다. 이 앱은 장고 프로젝트 생성시 다음처럼 자동으로 추가된다.

\config\settings.py

INSTALLED_APPS = [
    (... 생략 ...)
    'django.contrib.auth',
    (... 생략 ...)
]

django.contrib.auth 앱을 이용하면 로그인과 로그아웃 기능을 정말 쉽게 구현할 수 있다.

우선 아래와 같이 앱을 생성해 보자.

django-admin startapp accounts

config\settings.py
아래와 같이 앱등록

INSTALLED_APPS = [
...
    'accounts',
...
]

앱의 urls.py 파일을 사용하기 위해 config/urls.py 파일을 다음과 같이 수정

config\urls.py

urlpatterns = [
    ...
    path('account/', include('account.urls')),
    ...
]

accounts\urls.py

from django.contrib import admin
from django.urls import include, path

app_name = 'accounts'

urlpatterns = [ 
]

앱에 어떤 기능도 구현하지 않았으므로 urlpatterns는 빈 상태로 놔두자.

2.로그인 기능 구현

templates\layout\navbar.html
아래를 추가

        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="{% url 'accounts:login'%}">로그인</a>
        </li>

3.로그인 뷰

navbar.html 파일에서 템플릿 태그로 {% url 'accounts:login' %}를 사용했으므로 accounts/urls.py 파일에 다음과 같은 URL 매핑 규칙을 추가하자.

from django.contrib import admin
from django.urls import include, path

from django.contrib.auth import views as auth_views

app_name = 'accounts'

urlpatterns = [
     path('login/', auth_views.LoginView.as_view(), name='login'), 
]
여기까지 수정하고 브라우저에서 내비게이션바의 '로그인' 링크를 눌러 보자. 그러면 아마도 다음과 같은 오류 페이지가 나타날 것이다.

위 오류는 registration 디렉터리에 login.html 파일이 없음을 의미한다. 앞에서 사용한 LoginView는 registration이라는 템플릿 디렉터리에서 login.html 파일을 찾는다. 그런데 이 파일을 찾지 못해 오류가 발생한 것이다. 이 오류를 해결하려면 registration/login.html 템플릿 파일을 작성해야 한다.

하지만 로그인은 accounts 앱에 구현할 것이므로 오류 메시지에 표시한 것처럼 registration 디렉터리에 템플릿 파일을 생성하기보다는 accounts 디렉터리에 템플릿을 생성하는 것이 좋다. 이를 위해 LoginView가 accounts 디렉터리의 템플릿을 참조할 수 있도록 accounts/urls.py 파일을 다음과 같이 수정하자.

urlpatterns = [
     path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'), 
]

templates\accounts\login.html

{% extends "layout/base.html" %}
{% block content %}
  <div class="container my-3">
    <form method="post" action="{% url 'accounts:login' %}">
      {% csrf_token %}
      {% include "form_errors.html" %}
      <div class="mb-3">
        <label for="username">사용자ID</label>
        <input type="text" class="form-control" name="username" id="username" value="{{ form.username.value|default_if_none:'' }}">
      </div>
      <div class="mb-3">
        <label for="password">비밀번호</label>
        <input type="password" class="form-control" name="password" id="password" value="{{ form.password.value|default_if_none:'' }}">
      </div>
      <button type="submit" class="btn btn-primary">로그인</button>
    </form>
  </div>
{% endblock %}

templates\layout\form_errors.html

{% extends "layout/base.html" %}
{% block content %}
  <div class="container my-3">
    <form method="post" action="{% url 'accounts:login' %}">
      {% csrf_token %}
      {% include "layout/form_errors.html" %}
      <div class="mb-3">
        <label for="username">사용자ID</label>
        <input type="text" class="form-control" name="username" id="username" value="{{ form.username.value|default_if_none:'' }}">
      </div>
      <div class="mb-3">
        <label for="password">비밀번호</label>
        <input type="password" class="form-control" name="password" id="password" value="{{ form.password.value|default_if_none:'' }}">
      </div>
      <button type="submit" class="btn btn-primary">로그인</button>
    </form>
  </div>
{% endblock %}

form_errors.html 템플릿은 로그인 실패시 로그인이 왜 실패했는지 알려주는 역할을 한다. 폼 오류에는 다음과 같이 두 가지 종류의 오류가 있다.

필드 오류 (field.errors)
넌필드 오류 (form.non_field_errors)
필드 오류는 사용자가 입력한 필드 값에 대한 오류로 값이 누락되었거나 필드의 형식이 일치하지 않는 경우에 발생하는 오류이다. 넌필드 오류는 필드의 값과는 상관없이 다른 이유로 발생하는 오류이다. form_errors.html 템플릿은 필드 오류와 넌필드 오류 모두를 표시하기 위해 삽입되는 템플릿이다.

오류가 발생한 이유는 로그인이 성공하면 django.contrib.auth 패키지는 디폴트로 /accounts/profile/ 이라는 URL로 이동시키기 때문이다.

로그인은 성공한 것이 맞다.

로그인 성공 시 / 페이지로 이동할 수 있도록 config/settings.py 파일을 수정하자. 마지막 줄에 LOGIN_REDIRECT_URL을 추가하면 된다.

config\settings.py

로그인 성공후 이동하는 URL
LOGIN_REDIRECT_URL = '/'

추가후
아래 부분을 추가
config\urls.py

 path("", include('home.urls'),name='home'),

4.로그아웃

로그인에 성공했지만, 내비게이션바에는 여전히 "로그인" 링크가 보인다. 로그인 후에는 "로그인" 링크가 "로그아웃" 링크로 바뀌어야 할 것이다.

반대로 로그아웃 상태에서는 "로그인" 링크로 바뀌어야 한다.

navbar.html 템플릿 파일에서 로그인 링크 부분을 다음과 같이 수정하자.

        <li class="nav-item">
          {% if user.is_authenticated %}
          <a class="nav-link" href="{% url 'accounts:logout' %}">{{ user.username }} (로그아웃)</a>
          {% else %}
          <a class="nav-link active" aria-current="page" href="{% url 'accounts:login'%}">로그인</a>
          {% endif %}
        </li>

{% if user.is_authenticated %} 은 현재 사용자가 로그인 되었는지를 판별한다. 따라서 로그인이 되어 있으면 "로그아웃" 링크를 표시하고 로그인이 되어 있지 않다면 "로그인" 링크를 표시할 것이다.

로그인 상태에서는 로그아웃 링크에 사용자명 {{ user.username }}도 추가로 표시했다.

accounts\urls.py 추가

urlpatterns = [
     path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'), 
     path('logout/', views.logout_view, name='logout'),
]

accounts\views.py

from django.contrib.auth import logout
from django.shortcuts import redirect

# Create your views here.
def logout_view(request):
    logout(request)
    return redirect('/')

logout_view 함수가 호출되면 django.contrib.auth 모듈의 logout 함수를 사용하여 로그아웃을 수행하고 'index' 페이지로 리다이렉트하게 했다.

로그아웃이 잘 동작하는지 확인해 보자.

profile
쿵스보이(얼짱뮤지션)

0개의 댓글