Web/Django

장고(Django) 로그인, 로그아웃 페이지 구현하기, django.contrib.auth 활용

daeunnniii 2021. 8. 4. 02:38
728x90
반응형

이번에는 로그인, 로그아웃 기능을 구현해볼 것이다.

Django에서 로그인, 로그아웃을 도와주는 앱은 django.contrib.auth이다. 이 앱은 프로젝트 생성 시 settings.py에 자동으로 추가된다.

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

 

1. common 앱 생성

먼저 로그인, 로그아웃 기능을 구현할 앱을 추가해줄 것이다. 현재까지 게시판 기능을 구현한 'notes' 앱만 구현했으므로, 이제는 '공통 기능을 가진 앱'을 추가하여 구현할 것이다.

터미널에 아래와 같이 입력해서 common 앱을 생성하자.

> django-admin startapp common

그리고 settings.py에 'common.apps.CommonConfig'을 추가하여 common앱을 등록하고,

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('pybo/', include('pybo.urls')),
    path('common/', include('common.urls')),
]

그리고 common/urls.py 파일을 생성해서 다음과 같이 작성해준다.

app_name = 'common'

urlpatterns = [
]

 

2. 로그인

navbar.html에 "로그인" 링크를 아래와 같이 작성하여 로그인 화면으로 진입할 수 있도록 한다.

<ul class="navbar-nav">
    <li class="nav-item ">
        <a class="nav-link" href="{% url 'common:login' %}">로그인</a>
    </li>
</ul>

이제 네비게이션바에서 "로그인" 버튼 클릭 시 로그인 화면이 연결될 수 있도록 urls.py에서 URL 매핑을 추가해야한다.

from django.urls import path
from django.contrib.auth import views as auth_views

app_name = 'common'

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

그리고 django.contrib.auth 앱의 LoginView를 활용하면 로그인 뷰는 따로 만들 필요가 없다.

 

또 여기서 알아야할 점은, LoginView는 registration이라는 템플릿 디렉터리에서 login.html 파일을 찾는다. 그런데 우리는 common 앱에 로그인 기능을 구현할 것이므로 LoginView가 common 디렉터리의 템플릿을 참조할 수 있도록 common/urls.py를 아래와 같이 수정해주어야한다.

from django.urls import path
from django.contrib.auth import views as auth_views

app_name = 'common'

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

 

이렇게 설정을 완료했으면 이제 login.html 파일을 작성해주어야한다. common 템플릿 디렉터리에서 login.html 파일을 생성한 뒤 아래와 같이 작성한다.

{% extends "base.html" %}
{% block content %}
<div class="container my-3">
    <form method="post" class="post-form" action="{% url 'common:login' %}">
        {% csrf_token %}
        {% include "form_errors.html" %}
        <div class="form-group">
            <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="form-group">
            <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 %}

사용자 id를 입력하는 username과 비밀번호를 입력하는 password 항목은 django.contrib.auth 앱의 필수 요구항목이다. 그리고 include 태그로 포함된 form_errors.html을 또 추가로 작성해보자. 아래 코드의 경우 로그인 실패 시 로그인이 왜 실패했는지 알려주는 기능을 한다.

{% if form.errors %}
    {% for field in form %}
        {% for error in field.errors %}  <!-- 필드 오류를 출력한다. -->
            <div class="alert alert-danger">
                <strong>{{ field.label }}</strong>
                {{ error }}
            </div>
        {% endfor %}
    {% endfor %}
    {% for error in form.non_field_errors %}   <!-- 넌필드 오류를 출력한다. -->
        <div class="alert alert-danger">
            <strong>{{ error }}</strong>
        </div>
    {% endfor %}
{% endif %}

폼 오류는 크게 두가지로 나눌 수 있다.

1. 필드 오류(field.errors): 사용자가 입력한 필드 값에 대한 오류로 값이 누락되었거나 필드의 형식이 일치하지 않는 경우에 발생하는 오류

2. 넌필드 오류(form.non_field_errors): 필드의 값과는 상관없이 다른 이유로 발생하는 오류

 

이제 로그인 페이지를 들어가서 비밀번호를 입력하지 않고 로그인 버튼을 눌러본다. 아래와 같이 "비밀번호는 필수 항목입니다."라고 오류 메세지가 잘 표시되는 것을 볼 수 있다.

3. 로그인 후 페이지 이동 설정

django.contrib.auth 패키지는 로그인이 성공하면 디폴트로 /accounts/profile/ URL로 이동하게 되어있다.

하지만 이것은 우리의 목적과 맞지 않으므로 / 페이지로 이동할 수 있도록 수정할 것이다.

settings.py 파일에서 아래와 같이 LOGIN_REDIRECT_URL을 추가하면 된다.

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

이제 로그인 후 페이지 이동이 잘 작동한다.

 

4. 로그아웃 기능 구현

로그인에 성공했지만, 네비게이션 바에 여전히 "로그인"이라고 뜨는 것을 볼 수 있다. 로그인 후에는 "로그아웃"이 뜨도록 수정해야한다.

 

narbar.html을 아래와 같이 수정한다.

{% if user.is_authenticated %}은 현재 사용자가 로그인 되었는지 판별한다.

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

그러면 이제 URL 매핑을 해주어야한다. common/urls.py를 아래와 같이 수정한다.

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

그리고 로그아웃 시 리다이렉트할 페이지도 settings.py에 추가한다.

# 로그아웃시 이동하는 URL
LOGOUT_REDIRECT_URL = '/'

 

5. 결과 확인

이제 로그인을 하면 아래와 같이 네비게이션바에 "로그아웃" 버튼이 뜨고, 로그아웃 버튼 클릭 시 리다이렉트 되도록 설정한 페이지가 잘 뜨는 것을 볼 수 있다.

 

참고: https://wikidocs.net/71259

728x90
반응형