Django 로그인, 로그아웃 구현하기

2022. 2. 7. 13:32강의 정리/Django 기초

반응형

출처 : https://www.inflearn.com/course/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%A5%EA%B3%A0-%EC%9B%B9%EC%84%9C%EB%B9%84%EC%8A%A4/dashboard

 

장고(Django)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!

 


 

로그인 구현하기

아이디 / 암호를 통한 로그인

#accounts/views.py

from django.contrib.auth.views import LoginView

login = LoginView.as_view(tempalte_name= "accounts/login_form.html")
  • Django 클래스 뷰LoginView를 상속받습니다

 

https://github.com/django/django/blob/main/django/contrib/auth/views.py

 

GitHub - django/django: The Web framework for perfectionists with deadlines.

The Web framework for perfectionists with deadlines. - GitHub - django/django: The Web framework for perfectionists with deadlines.

github.com

class LoginView(SuccessURLAllowedHostsMixin, FormView):
    """
    Display the login form and handle the login action.
    """
    form_class = AuthenticationForm
    authentication_form = None
    next_page = None
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name = 'registration/login.html'
    redirect_authenticated_user = False
    extra_context = None

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        if self.redirect_authenticated_user and self.request.user.is_authenticated:
            redirect_to = self.get_success_url()
            if redirect_to == self.request.path:
                raise ValueError(
                    "Redirection loop for authenticated user detected. Check that "
                    "your LOGIN_REDIRECT_URL doesn't point to a login page."
                )
            return HttpResponseRedirect(redirect_to)
        return super().dispatch(request, *args, **kwargs)

    def get_success_url(self):
        return self.get_redirect_url() or self.get_default_redirect_url()

    def get_redirect_url(self):
        """Return the user-originating redirect URL if it's safe."""
        redirect_to = self.request.POST.get(
            self.redirect_field_name,
            self.request.GET.get(self.redirect_field_name, '')
        )
        url_is_safe = url_has_allowed_host_and_scheme(
            url=redirect_to,
            allowed_hosts=self.get_success_url_allowed_hosts(),
            require_https=self.request.is_secure(),
        )
        return redirect_to if url_is_safe else ''

    def get_default_redirect_url(self):
        """Return the default redirect URL."""
        return resolve_url(self.next_page or settings.LOGIN_REDIRECT_URL)

    def get_form_class(self):
        return self.authentication_form or self.form_class

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def form_valid(self, form):
        """Security check complete. Log the user in."""
        auth_login(self.request, form.get_user())
        return HttpResponseRedirect(self.get_success_url())

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        current_site = get_current_site(self.request)
        context.update({
            self.redirect_field_name: self.get_redirect_url(),
            'site': current_site,
            'site_name': current_site.name,
            **(self.extra_context or {})
        })
        return context

 

 

#accounts/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('signup/', views.signup, name='signup'),
    
    # /accounts/login/ => settings.LOGIN_URL에 문자열로 지정되어 있음
    path('login/', views.login, name='login'),
]

 

 

#프로젝트/templates/프로젝트/_form.html

{% load bootstrap4 %}


<div class="card">
    {% if form_title %}
        <div class="card-header">
            {{ form_title }}
        </div>
    {% endif %}
    <div class="card-body">
        <form action="" method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            {% bootstrap_form form %}
            {% buttons %}
            <button type="submit" class="btn btn-primary">
                Submit
            </button>
            {% endbuttons %}
        </form>
    </div>
  </div>
  • 만약 템플릿에 form_title이 지정되어있으면 카드의 헤더에 form_title을 노출 시킨다.

https://getbootstrap.kr/docs/5.0/components/card/

 

카드

여러 가지 종류와 옵션을 가진 유연하고 확장 가능한 콘텐츠를 제공합니다.

getbootstrap.kr

 

#accounts/templates/accounts/login_form.html

 

{% extends "accounts/layout.html" %}
{% load bootstrap4 %}

{% block content %}
    <div class="container">
        <div class="row">
            <div class="col-sm-6 offset-sm-3">
                {% include "_form.html" with form_title="로그인" submit_label="로그인"  %}
            </div>
        </div>
    </div>  
{% endblock %}

 

 


로그아웃

 

#accounts/views.py

from django.contrib.auth.views import LoginView, LogoutView, logout_then_login

#logout = LogoutView.as_view(template_name= "accounts/logout_form.html")

def logout(request):
    messages.success(request, '로그아웃 되었습니다!')
    return logout_then_login(request)
  • Django 클래스 뷰 LogoutView를 상속받습니다

https://github.com/django/django/blob/main/django/contrib/auth/views.py

 

GitHub - django/django: The Web framework for perfectionists with deadlines.

The Web framework for perfectionists with deadlines. - GitHub - django/django: The Web framework for perfectionists with deadlines.

github.com

 

class LogoutView(SuccessURLAllowedHostsMixin, TemplateView):
    """
    Log out the user and display the 'You are logged out' message.
    """
    next_page = None
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name = 'registration/logged_out.html'
    extra_context = None

    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        auth_logout(request)
        next_page = self.get_next_page()
        if next_page:
            # Redirect to this page until the session has been cleared.
            return HttpResponseRedirect(next_page)
        return super().dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        """Logout may be done via POST."""
        return self.get(request, *args, **kwargs)

    def get_next_page(self):
        if self.next_page is not None:
            next_page = resolve_url(self.next_page)
        elif settings.LOGOUT_REDIRECT_URL:
            next_page = resolve_url(settings.LOGOUT_REDIRECT_URL)
        else:
            next_page = self.next_page

        if (self.redirect_field_name in self.request.POST or
                self.redirect_field_name in self.request.GET):
            next_page = self.request.POST.get(
                self.redirect_field_name,
                self.request.GET.get(self.redirect_field_name)
            )
            url_is_safe = url_has_allowed_host_and_scheme(
                url=next_page,
                allowed_hosts=self.get_success_url_allowed_hosts(),
                require_https=self.request.is_secure(),
            )
            # Security check -- Ensure the user-originating redirection URL is
            # safe.
            if not url_is_safe:
                next_page = self.request.path
        return next_page

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        current_site = get_current_site(self.request)
        context.update({
            'site': current_site,
            'site_name': current_site.name,
            'title': _('Logged out'),
            'subtitle': None,
            **(self.extra_context or {})
        })
        return context

 

  • LogoutView에는 logout_then_login 함수가 존재한다.
    • logout_then_login  함수는 유저가 로그아웃 할 경우에 바로 로그인 페이지로 redirect 해주는 함수이다.
def logout_then_login(request, login_url=None):
    """
    Log out the user if they are logged in. Then redirect to the login page.
    """
    login_url = resolve_url(login_url or settings.LOGIN_URL)
    return LogoutView.as_view(next_page=login_url)(request)

 

 

#accounts/urls.py

from django.urls import path
from . import views

urlpatterns = [

    path('logout/', views.logout, name='logout'),

]

 


회원 가입과 동시에 로그인

 

#accounts/views.py

from django.contrib.auth import login as auth_login


def signup(request):
    """
    중략
    """
            auth_login(request, signed_user)
    """
    중략
    """
    })
  • Django auth에서 인증, 보안에 필요한 거의 모든 것들을 지원해주기 때문에 적극 활용하자 

 

https://github.com/django/django/tree/main/django/contrib/auth

 

GitHub - django/django: The Web framework for perfectionists with deadlines.

The Web framework for perfectionists with deadlines. - GitHub - django/django: The Web framework for perfectionists with deadlines.

github.com

 

 

반응형