파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.
앞서 인증 관련 강의에서 auth앱에 정의되어있는 View, Form을 커스텀해서 인증 기능을 구현해 본 바 있다.
본 글에서는 비밀번호 변경 폼을 django.contrib.auth.forms.PasswordChangeForm
과 django.contrib.auth.views.PasswordChangeView
를 커스텀해서 구현해 본다.
auth앱의 PasswordChangeView
상속받아서 커스텀해서 구현했다.
PasswordChangeForm
로 지정되어있다. 그러나 PasswordChangeForm
를 상속받아 우리의 폼을 정의 할 것이기 때문에 accounts의 PasswordChangeForm
로 지정해주었다.# 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 %}