회원가입
path('signup/', views.signup, name='signup')
from django.contrib.auth.forms import UserCreationForm
@require_http_methods(['GET', 'POST'])
def signup(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('index')
else:
form = UserCreationForm()
context = {'form': form}
return render(request, 'accounts/signup.html', context)
{% extends 'base.html' %}
{% block content %}
<h1>회원가입</h1>
<form action="{% url 'accounts:signup' %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">회원가입</button>
</form>
{% endblock content %}
일단 signup url, view, html 생성. 하던대로 하면 된다. 장고에서 제공하는 UserCreationForm()을 가져와 사용하면 됨.
하던대로 POST일때 valid 확인 후 저장 및 index 페이지로 redirect.
GET일때는 빈 폼 context로 받아 회원가입 페이지 렌더링.
회원가입 하면 바로 로그인 된 상태로 넘어가면 좋겠다.
@require_http_methods(['GET', 'POST'])
def signup(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
auth_login(request, user)
return redirect('index')
else:
form = UserCreationForm()
context = {'form': form}
return render(request, 'accounts/signup.html', context)
UserCreationForm은 save() 하는 순간 저장한 인스턴스를 돌려줌.
여기서의 인스턴스는 user
딱 한줄로 로그인 처리 auth_login(request, user)
편의성을 위해 회원가입 버튼 역시 모든 화면에서 보이도록 base.html을 수정해주자.
<body>
<div class="navbar">
{% if request.user.is_authenticated %}
<h3>Hello, {{ request.user.username }}</h3>
<form action="{% url 'accounts:logout' %}" method="POST">
{% csrf_token %}
<input type="submit" value="로그아웃"></input>
</form>
{% else %}
<a href="{% url 'accounts:login' %}">로그인</a>
<a href="{% url 'accounts:signup' %}">회원가입</a>
{% endif %}
</div>
<div class="container">
{% block content %}
{% endblock content %}
</div>
</body>
로그아웃 상태일때, 즉 esle문에 a태그를 추가해준다.
회원 탈퇴
delete로 또 만들어주자(urls, views)
path('delete/', views.delete, name='delete'),
@require_POST
def delete(request):
if request.user.is_authenticated:
request.user.delete()
return redirect('index')
request.user.delete()로 DB에서 삭제.
즉 해당 인스턴스에다 대고 delete 수행하면 된다.
<body>
<div class="navbar">
{% if request.user.is_authenticated %}
<h3>Hello, {{ request.user.username }}</h3>
<form action="{% url 'accounts:logout' %}" method="POST">
{% csrf_token %}
<input type="submit" value="로그아웃"></input>
</form>
<form action="{% url 'accounts:delete' %}" method="POST">
{% csrf_token %}
<input type="submit" value="회원탈퇴"></input>
</form>
{% else %}
<a href="{% url 'accounts:login' %}">로그인</a>
<a href="{% url 'accounts:signup' %}">회원가입</a>
{% endif %}
</div>
<div class="container">
{% block content %}
{% endblock content %}
</div>
</body>
회원탈퇴 역시 base.html에서 수정해준다.
당연히 POST 요청, 즉 form 필요하고 나머지는 동일.
회원탈퇴는 잘 되는데, 탈퇴 시 해당 유저의 세션이 남아있음. 이것도 지워주자.
@require_POST
def delete(request):
if request.user.is_authenticated:
request.user.delete()
auth_logout(request)
return redirect('index')
accounts의 views.py
간단하다. auth_logout(request) 한줄처리만 추가해주면 됨.
정보수정
역시 장고가 form을 제공. UserChangeForm()
path('update/', views.update, name='update'),
from django.contrib.auth.forms import (
AuthenticationForm,
UserChangeForm,
)
def update(request):
form = UserChangeForm(instance=request.user)
context = {'form': form}
return render(request, 'accounts/update.html', context)
{% extends 'base.html' %}
{% block content %}
<h1>회원 정보 수정</h1>
<form action="{% url 'accounts:update' %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">수정</button>
</form>
{% endblock content %}
하던대로 하면됨.
수정 페이지를 보면 너무 많은 정보가 수정가능하다. 필요한 부분만 수정할 수 있도록 커스텀 해보자
우선 accounts 앱 안에 forms.py 생성
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth import get_user_model
class CustomUserUpdateForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = [
'first_name',
'last_name',
'email',
]
forms.py
UserChangeForm을 상속받고, CustomUserUpdateForm이라는 이름으로 오버라이딩하여 사용하는 것.
get_user_model()을 사용.
수정 가능한 항목들을 fields 안에 입력해주면 된다.
from .forms import CustomUserChangeForm
def update(request):
form = CustomUserChangeForm(instance=request.user)
context = {'form': form}
return render(request, 'accounts/update.html', context)
views 도 CustomUserChangeForm을 사용하는 것으로 수정해줘야 함.
@require_http_methods(['GET', 'POST'])
def update(request):
if request.method == 'POST':
form = CustomUserChangeForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('index')
else:
form = CustomUserChangeForm(instance=request.user)
context = {'form': form}
return render(request, 'accounts/update.html', context)
update 로직 구현. 하던대로 하면 되는데 instance가 필요하다.
그냥 닫으면 새로운 데이터를 생성하게 됨.
이건 "수정" 이기 때문에 instance를 같이 넣어서 해당 instance에 방금 내용을 업데이트해야 한다.
<body>
<div class="navbar">
{% if request.user.is_authenticated %}
<h3>Hello, {{ request.user.username }}</h3>
<form action="{% url 'accounts:logout' %}" method="POST">
{% csrf_token %}
<input type="submit" value="로그아웃"></input>
</form>
<a href="{% url 'accounts:update' %}">회원정보수정</a>
<form action="{% url 'accounts:delete' %}" method="POST">
{% csrf_token %}
<input type="submit" value="회원탈퇴"></input>
</form>
{% else %}
<a href="{% url 'accounts:login' %}">로그인</a>
<a href="{% url 'accounts:signup' %}">회원가입</a>
{% endif %}
</div>
<div class="container">
{% block content %}
{% endblock content %}
</div>
</body>
마지막으로 역시 모든 페이지에서 보이도록 base.html에서 수정.
로그인 상태에서 보여야 하므로 if 안에 작성. a태그 하나 만들어준다.
비밀번호 수정
역시역시 장고가 PasswordChangeForm을 제공
path('password/', views.change_password, name='change_password'),
from django.contrib.auth.forms import (
AuthenticationForm,
PasswordChangeForm,
)
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
form.save()
return redirect('index')
else:
form = PasswordChangeForm(request.user)
context = {'form': form}
return render(request, 'accounts/change_password.html', context)
누구의 password를 바꾸는지 받기 위해 request.user를 받아온다.
{% extends 'base.html' %}
{% block content %}
<h1>비밀번호 변경</h1>
<form action="{% url 'accounts:change_password' %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">비밀번호 변경</button>
</form>
{% endblock content %}
하던대로 하자.
그런데 비밀번호를 바꾸면 로그인이 풀린다.
기존 세션의 인증 정보가 일치하지 않게 되고, 로그인이 풀리게 되는 것.
로그인이 풀리지 않기 위해 우리는 update_session_auth_hash(request, form.user)를 사용해야 한다.
사용해보자.
from django.contrib.auth import update_session_auth_hash
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
return redirect('index')
else:
form = PasswordChangeForm(request.user)
context = {'form': form}
return render(request, 'accounts/change_password.html', context)
save() 이후 update_session_auth_hash(request, form.user)를 해준다.
비밀번호를 변경하기 위해 this form 누르면 연결이 안되는데?
커스텀으로 해주자.
from django.urls import reverse
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = [
'first_name',
'last_name',
'email',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.fields.get("password"):
password_help_text = (
"You can change the password " '<a href="{}">here</a>.'
).format(f"{reverse('accounts:change_password')}")
self.fields["password"].help_text = password_help_text
역시 상속받아서 사용하면 된다.
오늘의 회고
특강이 많아서 진도를 못나갔다..
주말에 할게 더 많아짐
내일의 목표는 강의 세개 마저 듣기