01. 회원가입
02. 회원탈퇴
03. 정보 수정
04. 비밀번호변경
01. 회원가입
- Django는 기본 auth.User를 가지고 있기에 이를 기반으로한 기본적인 회원가입 ModelForm을 제공
- UserCreationForm
- username과 password 로 새로운 user를 생성하는 ModelForm
- username, password1, password2를 가짐
# (signup) accounts/forms.py
from django import forms
class ArticleForm(forms.Form):
title = forms.CharField(max_length=10)
content = forms.CharField()
# (signup) accounts/views.py
from django.contrib.auth.forms import UserCreationForm
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)
#(signup) accounts/templates/accounts/signup.html
{% 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 %}
# (signup) base.html
<a href="{% url 'accounts:signup'%}">회원가입</a>
- 가입하고 바로 로그인까지
- 로그인? → 세션 생성해주기 → django가 해주던데 → login()
#(session) accounts/views.py
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)
02. 회원탈퇴
# accounts/urls.py
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
path("login/", views.login, name="login"),
path("logout/", views.logout, name="logout"),
path("signup/", views.signup, name="signup"),
path("delete/", views.delete, name="delete"),
]
# accounts/views.py
@require_POST
def delete(request):
if request.user.is_authenticated:
request.user.delete()
return redirect("index")
- 만약 탈퇴하면서 해당 유저의 세션도 지우고 싶다면?
→ logout()을 사용
@require_POST
def delete(request):
if request.user.is_authenticated:
request.user.delete()
auth_logout(request)
return redirect("index")
탈퇴하고 → 세션지우고. 이 순서가 바뀌면 안됨
# base.html
<form action="{% url "accounts:delete" %}" method="POST">
{% csrf_token %}
<input type="submit" value="회원탈퇴"></input>
</form>
03. 정보 수정
# (update) accounts/urls.py
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
...
path("update/", views.update, name="update"),
]
# (update) acounts/views.py
from django.views.decorators.http import require_http_methods
from django.contrib.auth.forms import (
...
UserChangeForm,
)
...
@require_http_methods(["GET", "POST"])
def update(request):
if request.method == "POST":
pass
else:
form = UserChangeForm(instance=request.user)
context = {"form": form}
return render(request, "accounts/update.html", context)
# accounts/templates/accounts/update.html
{% extends "base.html" %}
{% block content %}
<h1>회원정보수정</h1>
<form action="{% url 'accounts:update' %}" method="POST">
{{ form.as_p }}
{% csrf_token %}
<button type="submit">수정하기</button>
</form>
{% endblock %}
# (update) base.html
<a href="{% url "accounts:update" %}">회원정보수정</a>
유저가 수정하면 안될 정보까지 다 보임
→ 필요한 기능이 있지만 내가 커스텀 하고 싶다면?
→ 상속을 통한 Form 커스텀
CustomUserChangeForm 만들기
# (update) accounts/forms.py
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth import get_user_model
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = # 적어야하는데 모르겠단말이지
- get_user_model()
- 현재 프로젝트에서 활성화 되어있는 유저모델을 반환
- 직접 User 모델을 import 할 수 있지만 get_user_model 을 사용하기를 권장
- django는 다중 User 모델을 지원하므로 확장에 용이
- 프로젝트의 유연성과 확장성을 높여줌
# (update) accounts/forms.py 수정
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth import get_user_model
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = (
"username",
"email",
"first_name",
"last_name",
)
accounts/views.py 완성시키기
# (update) accounts/views.py 완성
@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)
04. 비밀번호변경
PasswordChangeForm
- 유저의 비밀번호를 변경할 수 있는 Form을 제공
# (password) urls.py
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
...
path("password/", views.change_password, name="change_password"),
]
# (password) views (1차)
from django.contrib.auth.forms import (
...
PasswordChangeForm,
)
@login_required
@require_http_methods(["GET", "POST"])
def change_password(request):
form = PasswordChangeForm(request.user)
context = {"form": form}
return render(request, "accounts/change_password.html", context)
# change_password.html
{% 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 %}
비밀번호를 바꾸는 링크를 제공하지만, 우리가 원하는 링크가 아님. ( /accounts/password/ )이 경로로 커스터마이징 하자!
→ 오버라이딩(Overriding)
- CustomUserUpdateForm
- 상속받고 있는 기존 UserChangeForm을 살펴보면
오버라이딩해서 수정하기
# (password) CustomUserChangeForm
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = (
"username",
"email",
"first_name",
"last_name",
)
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
views 완성하기
# (password) views (2차)
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)
그런데 비밀번호를 한 번 변경해보면
비밀번호를 변경하면 기존 세션의 인증 정보와 일치하지 않기 때문에 로그인이 풀리게 됨
https://docs.djangoproject.com/en/4.2/topics/auth/default/#session-invalidation-on-password-change
# (password) views (완성)
@login_required
@require_http_methods(["GET", "POST"])
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)
'Django' 카테고리의 다른 글
Admin (0) | 2024.08.19 |
---|---|
Django Static, Media(runserver) (1) | 2024.08.19 |
Auth (0) | 2024.08.17 |
URL Namespace / Templates Namespace (Django 플젝 시작 시 유의사항) (0) | 2024.08.16 |
Django Form, Django Model Form (0) | 2024.08.16 |