Project using python/Cloning Airbnb
django change password by FBV
Cog Factory
2021. 3. 5. 14:08
url 설정
config/urls.py
urlpatterns = [
path("users", include("users.urls", namespace="users")),
]
users/urls.py
from django.urls import path
from . import views
app_name = "users"
urlpatterns = [path("<int:pk>/change-password/", views.change_password, name="change-password")]
{% url %}
update_profile.html의 일부다. Change Password button을 누르면 password를 수정할 수 있는 page로 간다. url template tag를 이용해서 update_profile page로 갈 수 있게 한다. {% url 'users:change-password' user.pk %}는 /users/<int:pk>/change-password/와 같다.
FBV(Function Based View)
users/views.py
FBV에서는 if 문으로 GET method 요청이 왔을 때와 POST method 요청이 왔을 때를 구분한다. GET은 page를 보여주고 POST는 client로부터 온 data를 처리한다.
# users/views.py
from django.shortcuts import render, redirect, reverse
from django.contrib.auth import authenticate, login
from django.contrib import messages
from .exception import VerifyUser
class EmailLoggedInOnly(Exception):
pass
@login_required
def change_password(request, pk):
if request.method == "GET":
try:
if request.user.login_method != "email":
raise EmailLoggedInOnly("Page not found 404")
if request.user.pk != pk:
raise VerifyUser("Page Not found 404")
user = models.User.objects.get_or_none(pk=pk)
if user is None:
messages.error(request, "User does not exist")
return redirect(reverse("core:home"))
return render(
request,
"pages/users/change_password.html",
context={"user": user},
)
except VerifyUser as error:
messages.error(request, error)
return redirect("core:home")
except EmailLoggedInOnly as error:
messages.error(request, error)
return redirect("core:home")
elif request.method == "POST":
try:
if request.user.login_method != "email":
raise EmailLoggedInOnly("Page not found 404")
if request.user.pk != pk:
raise VerifyUser("Page Not found 404")
user = models.User.objects.get_or_none(pk=pk)
if user is None:
messages.error(request, "User does not exist")
return redirect(reverse("core:home"))
old_password = request.POST.get("current_password")
new_password = request.POST.get("new_password")
new_password1 = request.POST.get("verify_password")
user = authenticate(request, username=user.email, password=old_password)
if user is None:
raise ChangePasswordException("Current password is wrong!")
if new_password != new_password1:
raise ChangePasswordException("New password doesn't match")
user.set_password(new_password)
user.save()
messages.success(request, f"{user.email}'password changed successfully")
login(request, user)
return redirect(reverse("users:profile", kwargs={"pk": pk}))
except ChangePasswordException as error:
messages.error(request, error)
return redirect(reverse("core:home"))
except VerifyUser as error:
messages.error(request, error)
return redirect("core:home")
except EmailLoggedInOnly as error:
messages.error(request, error)
return redirect("core:home")
templates
pages/users/change_password.html
{% csrf_token %}은 csrf 공격을 막기 위한 token이다. django는 보안이 뛰어나기 때문에 {% csrf_token %} tag를 사용하지 않으면 submit이 안 된다. csrf 공격의 보안은 절대 client를 신뢰하지 않는 것으로 시작한다. 즉, 이 token 값을 가지지 않은 브라우저 요청은 받아들이지 않는다.
{% extends 'base.html' %}
{% block page_title %}
Change {{user.first_name}}'s Password
{% endblock page_title %}
{% block search-bar %}
<div></div>
{% endblock search-bar %}
{% block content %}
<div class="background">
<div class="wrap">
<h1 class="font-bold text-xl mb-6">Change password of {{user.email}}</h1>
<form method="post" class="form">
{% csrf_token %}
<div class="form_input rounded-tl-lg rounded-tr-lg">
<input type="password" name="current_password" id="current_password" placeholder="Your current password">
</div>
<div class="form_input">
<input type="password" name="new_password" id="new_password" placeholder="New password">
</div>
<div class="form_input rounded-bl-lg rounded-br-lg">
<input type="password" name="verify_password" id="verify_password" placeholder="Verify your new password">
</div>
<button class="form_button bg-red-500">Change Password</button>
</form>
<button class="button bg-gray-700">
<a href="{% url 'users:profile' user.pk %}">Back</a>
</button>
</div>
</div>
{% endblock content %}
참고 자료
- 노마드 코더의 Airbnb 클론 강의
- {% csrf_token %}
소스 코드
github.com/zpskek/airbnb-clone-v3/commit/6f1a9c78929d793322dd95f979b4cba93325c6fc