로그인은 인증(Authentication)과 인가(Authorization)가 결합된 기능
인증 (Authentication)
사용자가 누구인지 확인하는 과정
인가 (Authorization)
인증된 사용자가 무엇을 할 수 있는지 결정하는 과정
인증 => settings.py에서 INSTALLED_APPS의 "django.contrib.auth"
config/settings.py INSTALLED_APPS에 "common" 추가
# settings.py
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"pybo", # dev_2
"common", # dev_12
]
config/urls.py urlpatterns에 common path 추가
# urls.py
urlpatterns = [
path("admin/", admin.site.urls), # http://127.0.0.1:8000
path("pybo/", include("pybo.urls")),
path("common/", include("common.urls")),
]
common 폴더 안에 urls.py 생성
app_name = "common"
urlpatterns = []
templates 폴더의 nav_bar.html에서 로그인 href 설정
<a class="nav-link" href="{% url 'common:login' %}">로그인</a>
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",
),
]
registration/login.html이 있어야 한다.

templates/common/login.html 생성
{% extends "base.html" %}
{% block content %}
<div class="container my-3">
<form method="post" action="{% url 'common: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/form_errors.html 생성
<!-- 필드 오류와 넌필드 오류를 출력한다. -->
{% if form.errors %}
<div class="alert alert-danger">
{% for field in form %}
<!-- 필드 오류 -->
{% if field.errors %}
<div>
<strong>{{ field.label }}</strong>
{{ field.errors }}
</div>
{% endif %}
{% endfor %}
<!-- 넌필드 오류 -->
{% for error in form.non_field_errors %}
<div>
<strong>{{ error }}</strong>
</div>
{% endfor %}
</div>
{% endif %}


현재 로그인이 가능한 사용자는 슈퍼유저로 생성한 "admin" 뿐이라 admin으로 로그인해보자.
http://127.0.0.1:8000/accounts/profile/

config/settings.py의 밑에 코드를 추가
# 로그인 성공후 이동하는 URL
LOGIN_REDIRECT_URL = '/'
config\urls.py에 path를 작성하고 pybo의 views를 import 한다
from django.contrib import admin
from django.urls import include, path
from pybo import views
# http://127.0.0.1:8000
urlpatterns = [
path("admin/", admin.site.urls), # http://127.0.0.1:8000
path("pybo/", include("pybo.urls")),
path("common/", include("common.urls")),
path("", views.index, name="index"),
]
로그인 성공!

templates/navbar.html의 nav-item 안을 수정
원래는 로그인 해도 로그인으로 떴었는데 이젠 로그인하면 로그아웃이 뜬다.
<!-- 네비게이션바 -->
<nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom">
<div class="container-fluid">
<a class="navbar-brand" href="{% url 'pybo:index' %}">Pybo</a>
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<!-- dev_13 -->
{% 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>
</ul>
</div>
</div>
</nav>
common/urls.py에 logout path 추가
common에서 views import
# dev_13
from django.urls import path
from django.contrib.auth import views as auth_views
from common import views
app_name = "common"
urlpatterns = [
path(
"login/",
auth_views.LoginView.as_view(template_name="common/login.html"),
name="login",
), # dev_13
path(
"logout/",
views.logout_view,
name="logout",
), # dev_13
]
로그아웃을 수행하고 'index' 페이지로 리다이렉트
common/views.py
from django.contrib.auth import logout
from django.shortcuts import redirect
def logout_view(request):
logout(request)
return redirect('index')
로그아웃 완료!

