로그인 기능을 ajax로 만들자!

우선 ajax를 사용하기 위해서 JQuery 를 가져와야한다!

그리고 bootstrapalert 디자인도 넣었고,

ajax 함수도 넣었다!

templates/base.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{%block title%}{% endblock %}</title>
    <script src="<https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js>" integrity="sha384-KsvD1yqQ1/1+IA7gi3P0tyJcT3vR+NdBTt13hSJ2lnve8agRGXTTyNaBYmCR/Nwi" crossorigin="anonymous"></script>
    <!-- ajax -->
    <script src="<https://code.jquery.com/jquery-3.5.1.min.js>" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <script src="<https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js>" integrity="sha384-nsg8ua9HAw1y0W1btsyWgBklPnCUAFLuTMS2G72MMONqmOymq585AcH49TLBQObG" crossorigin="anonymous"></script>
    <link href="<https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css>" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
    <link rel="stylesheet" href="<https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css>">
    <script>
    $(function () {
        $('.login-form').on('submit', function(e){
            AjaxLogin(e);
        });
    });

    AjaxLogin = (e) => {
        e.preventDefault();
        // 백엔드 서버에 요청
        var request = $.ajax({
            method: 'POST',
            // html 맨 위에 설정한 urls
            url: "{% url 'accounts:login' %}",
            async: false,
            data: $('.login-form').serialize()
        });
        request.done(function (data){
            if (data.works){
                $(location).attr('href', location.origin);
            } else {
                $('#error_message').html(data.error_message);
            }
        });
        request.fail(function (jqXHR, textStatus){
            if (jqXHR.status == 404){
                alert("페이지가 존재하지 않습니다.");
            } else if (jqXHR.status == 403) {
                alert("로그인 해주세요.");
            } else {
                alert("문제가 발생했습니다. 다시 시도해주세요.");
            }
        });
        return false;
    }
    </script>
    {% block script %}
    {% endblock %}

    {% block style %}
    {% endblock %}
</head>
<body>
    <div class="container">
        <div class="row flex-nowrap justify-content-between align-items-center py-2 border-bottom">
            <div class="col-4"></div>
            <div class="col-4 text-center">TEST MY SITE</div>
            <div class="col-4 d-flex justify-content-end align-items-center">
                <!-- Button trigger modal -->
                <button type="button" class="btn btn-sm btn-light me-1 mt-0" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
                    로그인
                </button>
                <button class="btn btn-sm btn-light">회원가입</button>
            </div>
        </div>
        <nav class="navbar navbar-expand-lg navbar-light">
            <div class="container-fluid">
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarNavDropdown">
                    <ul class="navbar-nav">
                        {% for board in nav_board %}
                        <li class="nav-item">
                            <a class="nav-link" href="#">{{board.name}}</a>
                        </li>
                        {% endfor %}
                        <li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                            다양한메뉴
                            </a>
                            <ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                                <li><a class="dropdown-item" href="#">다양한메뉴1</a></li>
                                <li><a class="dropdown-item" href="#">다양한메뉴2</a></li>
                                <li><a class="dropdown-item" href="#">다양한메뉴3</a></li>
                            </ul>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
        <div class="row">
            <div class="col-12 mb-3">{% block top %}{% endblock %}</div>
            <div class="col-sm-12 col-md-7 col-lg-8 col-xl-8 col-xxl-9">{% block middle_left %}{% endblock %}</div>
            <div class="col-sm-12 col-md-5 col-lg-4 col-xl-4 col-xxl-3">{% block middle_right %}{% endblock %}</div>
        </div>
    </div>
    <footer class="footer py-3 mt-3 bg-light">
        <div class="container text-center">
            <div class="text-muted fs-6">Place sticky footer content here.</div>
            <div class="text-muted fs-6">Place sticky footer content here.</div>
            <div class="text-muted fs-6">Place sticky footer content here.</div>
        </div>
    </footer>
    <!-- Modal -->
    <div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header">
            <h5 class="modal-title" id="staticBackdropLabel">로그인</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <div class="mb-3">
                    <div class="fw-bold mb-2">일반 로그인</div>
                    <form class="login-form" mehtod="POST" action="">
                        {% csrf_token %}
                        <input class="form-control mb-2" type="text" name="username" placeholder="아이디"/>
                        <input class="form-control mb-2" type="password" name="password" placeholder="비밀번호"/>
                        <div class="d-grid gap-2">
                            <input class="btn text-white" style="background-color: rgb(82, 121, 250);" type="submit" value="로그인"/>
                        </div>
                    </form>
                </div>
                <div id="error_message" class="alert alert-danger text-center" role="alert">로그인 해주세요!</div>
                <div class="mb-3">
                    <div class="fw-bold mb-2">소셜 로그인</div>
                    <div class="d-grid gap-2">
                        <button class="btn text-white" style="background-color: rgb(255, 78, 55);background-size:30px auto;background-image:url('{% static 'google_icon.png' %}');background-repeat:no-repeat;background-position:15px center;">Google 로그인</button>
                        <button class="btn text-white" style="background-color: rgb(50, 89, 219);background-size:30px auto;background-image:url('{% static 'facebook_icon.png' %}');background-repeat:no-repeat;background-position:15px center;">Facebook 로그인</button>
                        <button class="btn" style="background-color: rgb(248, 198, 80);background-size:30px auto;background-image:url('{% static 'kakao_icon.png' %}');background-repeat:no-repeat;background-position:15px center;">KaKao 로그인</button>
                        <button class="btn" style="background-color: rgb(88, 250, 59);background-size:30px auto;background-image:url('{% static 'naver_icon.png' %}');background-repeat:no-repeat;background-position:15px center;">Naver 로그인</button>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <div class="fs-6">새로운 회원이신가요? <a href="">회원가입하기</a></div>
            </div>
        </div>
        </div>
    </div>
</body>
</html>

완벽한 기능 수행을 위해서 views.py 로그인 관련 함수를 만들자

accounts/views.py

from django.shortcuts import render
from django.contrib import auth
from django.http import HttpResponse
import json

# Create your views here.
def login(request):
    if request.method == 'POST':
        username = request.POST.get("username")
        password = request.POST.get("password")

        user = auth.authenticate(request, username=username, password=password)

        if user is not None:
            auth.login(request, user)
            return HttpResponse(json.dumps({'works':True,}), 'application/json')
        else:
            return HttpResponse(json.dumps({'works':False, 'error_message':'아이디 혹은 비밀번호 오류'}), 'application/json')

이 기능을 묶기 위해서 urls.py 파일을 만들어 config/urls.py 와 묶자

config/urls.py

from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('board.urls')),
    path('accounts/', include('accounts.urls')),
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

이제 accounts/views.py 에 작성한 함수를 accounts/urls.py 에 묶자

accounts/urls.py