장고 프로젝트 중에 사용자 비밀번호를 바꾸는 기능을 구현하려고 했다.
로직은 이렇다.
만약 현재 비밀번호가 DB에 저장된 User 데이터의 비밀번호와 같다면, 그리고 새 비밀번호와 새 비밀번호 확인이 같다면 DB에 저장된 User 데이터의 비밀번호 값에 사용자가 입력한 새 비밀번호의 값을 저장해주자.
템플릿의 코드는 이렇다.
<form action="생략" method = "post">
{% csrf_token %}
<div>
현재 비밀번호 : <input type="password" name="password">
</div>
<div>
새 비밀번호 : <input type="password" name="new_password">
</div>
<div>
새 비밀번호 확인 : <input type="password" name="new_password_check">
</div>
<button type="submit">변경하기</button>
</form>
views.py의 코드 로직은 이렇다.
def ___(request, user_id) :
if request.method == "GET":
...
elif request.method == "POST":
my_p = User.objects.get(id=user_id) # DB User 테이블의 id값과 함수가 받은 인자 user_id 값이 같은 인스턴스(row) 데이터를 my_p라는 변수에 담는다.
if request.POST['password'] == my_p.password:
if request.POST['new_password'] == request.POST['new_password_check']:
my_p.password = request.POST['new_password']
my_p.save()
return redirect(f'/profile/{my_p.id}/')
else :
...
else :
...
else:
...
DB에서 가져온 User 인스턴스 데이터의 비밀번호와 사용자가 현재 비밀번호에 입력한 값이 같으면, 그리고 새 비밀번호에 입력된 값과 새 비밀번호 확인에 입력된 값이 같을 경우 DB에 있는 해당 User 데이터의 비밀번호 값을 사용자가 입력한 새 비밀번호로 저장한다.
결과는, 현재 비밀번호부터 같지 않다는 에러가 났다.
알아보니, DB에서 가져온 User 인스턴스 데이터의 비밀번호는 저장될 때 해싱처리되어 저장되기 때문에 그 해싱된 값과 비교해서 다르다는 결과가 나오는 것이다.
장고에는 비밀번호 변경을 위해 사용자가 입력한 비밀번호 값과 DB에 저장된 사용자의 비밀번호를 비교해주는 check_password라는 함수 기능이 있다.
check_password 함수는 두 개의 인자만을 받으며, 첫 번째 인자로는 사용자가 브라우저에서 입력한 값을 받고, 두 번째 인자로는 DB에 저장된 비밀번호 값을 받는다.
이 함수는 자동으로 이 두 인자 값을 비교하며 자동으로 'True면'이라는 조건을 부여한다.
코드로 나타내면 아래와 같다.
def ___(request, user_id):
if request.method == "GET":
my_password = User.objects.get(id=user_id)
return render(request, 'password.html', {"tem_my_password": my_password})
elif request.method == "POST":
my_p = User.objects.get(id=user_id)
if check_password(request.POST['password'], my_p.password):
if request.POST['new_password'] == request.POST['new_password_check']:
my_p.set_password(request.POST['new_password'])
my_p.save()
return redirect(f'/profile/{my_p.id}/')
else:
...
else:
...
else:
...
check_password 함수가 두 인자 값을 비교해서 True이면 사용자가 입력한 '새 비밀번호'와 '새 비밀번호 확인'의 값을 비교하고, 이것이 True라면 가져온 인스턴스 데이터의 비밀번호에 set_password라는 함수로 사용자가 POST요청으로 보낸 새 비밀번호 값을 넣어주고, save()함수로 값을 저장한다.
check_password : 장고에서 제공하는 함수로 받은 두 개의 인자를 비교해서 'True면'이라는 조건을 부여한다. 첫 번째 인자로는 사용자가 브라우저에서 입력한 값을 받고, 두 번째 인자로는 DB에 저장된 비밀번호 값을 받는다.
DB의 모델 데이터 인스턴스.set_password : 사용자가 입력한 새 비밀번호 값을 DB의 데이터에 지정
DB의 모델 데이터 인스턴스.save() : 새롭게 갱신된 데이터를 저장
받는 인자 값의 순서가 중요하다.