auth앱의 PasswordChangeForm 커스텀을 통한 암호 수정 구현

guava·2022년 1월 3일
1

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.

앞서 인증 관련 강의에서 auth앱에 정의되어있는 View, Form을 커스텀해서 인증 기능을 구현해 본 바 있다.

본 글에서는 비밀번호 변경 폼django.contrib.auth.forms.PasswordChangeFormdjango.contrib.auth.views.PasswordChangeView를 커스텀해서 구현해 본다.

auth앱PasswordChangeView 상속받아서 커스텀해서 구현했다.

  1. success_url을 지정해서 성공 이후 리디렉션 할 URL을 지정하였다.
  2. template_name에 템플릿 위치를 지정했다. 지정하지 않으면 admin의 비밀번호 변경 템플릿이 디폴트다.
  3. form_class는 지정하지 않으면 auth앱에서 제공하는 PasswordChangeForm로 지정되어있다. 그러나 PasswordChangeForm를 상속받아 우리의 폼을 정의 할 것이기 때문에 accountsPasswordChangeForm로 지정해주었다.
# accounts/views.py

from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.views import (
    LoginView, logout_then_login,
    PasswordChangeView as AuthPasswordChangeView
)
from accounts.forms import PasswordChangeForm  # 커스텀 폼 임포트

# ...

class PasswordChangeView(LoginRequiredMixin, AuthPasswordChangeView):
    success_url = reverse_lazy('password_change')
    template_name = 'accounts/password_change_form.html'  # 템플릿 위치 재정의
    form_class = PasswordChangeForm  # 커스텀 폼 지정

    def form_valid(self, form):  # 유효성 검사 성공 이후 로직 입력
        messages.success(self.request, '암호를 변경했습니다.')  # 성공 메시지
        return super().form_valid(form)  # 폼 검사 결과를 리턴해야한다.

password_change = PasswordChangeView.as_view()
# accounts/urls.py
from django.urls import path
from . import views

urlpatterns = [
    # ...
    path('password_change/', views.password_change, name='password_change')
]

PasswordChangeForm를 상속받아서 폼을 커스텀하였다.

이전 비밀번호와 새로운 비밀번호를 비교해서 같은 암호를 입력하였다면, 유효성검사를 통과하지 못하도록 하였다.

from django import forms
from django.contrib.auth.forms import (
    UserCreationForm,
    PasswordChangeForm as AuthPasswordChangeForm
)

class PasswordChangeForm(AuthPasswordChangeForm):
    # clean_new_password2 재정의 시에는 super()함수 호출이 필요하다. (부모에 존재하는 유효성 검사이다.)
    def clean_new_password1(self):
        # new_password1에 대한 유효성 검사를 추가로 정의한다.
        old_password = self.cleaned_data.get('old_password')
        new_password1 = self.cleaned_data.get('new_password1')

        if old_password and new_password1:
            if old_password == new_password1:  # 기존 암호와 같을 경우 폼 에러를 일으킨다.
                raise forms.ValidationError('새로운 암호는 기존 암호와 다르게 입력해주세요')
        return new_password1

템플릿

accounts/templates/accounts/password_change_form.html

{% extends 'accounts/layout.html' %}

{% 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 %}

0개의 댓글