회원 가입
- 회원 가입시 사용자 입력 데이터를 받는 built-int ModelForm
from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
path('signup/', views.signup, name='signup'),
]
<h1>회원가입</h1>
<form action="{% url 'accounts:signup' %}" method="POST">
{% csrf_token %}
{{form.as_p}}
<input type = "submit">
</form>
def signup(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('articles:index')
else:
form = UserCreationForm()
context = {
'form' : form,
}
return render(request, 'accounts/signup.html', context)
회원 가입 로직 에러
- 회원 가입에 사용하는 UserCreationForm이 기존 유저 모델로 인해 작성된 클래스이기 때문
- 대체한 유저 모델로 변경 필요
class Meta:
model = user
fields = ("username",)
field_classes = {"username": UsernameField}
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = get_user_model()
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = get_user_model()
get_user_model()
- 현재 프로젝트에서 활성화된 사용자 모델(active user model)을 반환하는 함수
User 모델을 직접 참조하지 않는 이유
- get_user_model()을 사용해 User 모델을 참조하면 커스텀 User 모델을 자동으로 반환해주기 때문
- Django는 필수적으로 User 클래스를 직접 참조하는 대신 get_user_model()을 사용해 참조해야 한다고 강조하고 있음.
회원가입 로직 custom 적용
from .forms import CustomUserCreationForm
def signup(request):
if request.method == 'POST':
form = CustomUserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('articles:index')
else:
form = CustomUserCreationForm()
context = {
'form' : form,
}
return render(request, 'accounts/signup.html', context)
회원 탈퇴
app_name = 'accounts'
urlpatterns = [
path('delete/', views.delete, name='delete'),
]
<form action="{% url 'accounts:delete' %}" method = "POST">
{% csrf_token %}
<input type="submit" value="회원탈퇴">
</form>
def delete(request):
request.user.delete()
return redirect('articles:index')
회원정보 수정
- 회원정보 수정 시 사용자 입력 데이터를 받는 built-in ModelForm
app_name = 'accounts'
urlpatterns = [
path('update/', views.update, name='update'),
]
<h1>회원정보 수정</h1>
<form action="{% url 'accounts:update' %}" method = "POST">
{% csrf_token %}
{{form.as_p}}
<input type = "submit">
</form>
from .forms import CustomUserChangeForm
def update(request):
if request.method =='POST':
pass
else:
form = CustomUserChangeForm(instance=request.user)
context = {
'form' : form,
}
return render(request, 'accounts/update.html', context)
<a href = "{% url 'accounts:update' %}">회원정보 수정</a>
- User 모델의 모든 정보들까지 모두 출력되어 수정이 가능하기 때문에 일반 사용자들이 접근해서는 안되는 정보는 출력하지 않도록 해야 함
- CustomUserChangeForm에서 접근 가능한 필드를 다시 조정
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = get_user_model()
fields = ('first_name', 'last_name', 'email',)
def update(request):
if request.method == 'POST':
form = CustomUserChangeForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('articles:index')
else:
form = CustomUserChangeForm(instance=request.user)
context = {
'form' : form,
}
return render(request, 'accounts/update.html', context)
비밀번호 변경
- 인증된 사용자의 Session 데이터를 Update 하는 과정
- 비밀번호 변경 시 사용자 입력 데이터를 받는 built-in Form
app_name = 'accounts'
urlpatterns = [
path('<int:user_pk>/password', views.change_password, name='change_password'),
]
<h1>회원정보 수정</h1>
<form action="{% url 'change_password' user.pk %}" method = "POST">
{% csrf_token %}
{{form.as_p}}
<input type = "submit">
</form>
from django.contrib.auth.forms import PasswordChangeForm
def change_password(request):
if request.method =='POST':
pass
else:
form = PasswordChangeForm(request.user)
context = {
'form' : form,
}
return render(request, 'accounts/change_password.html', context)
def change_password(request, user_pk):
if request.method = 'POST':
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
form.save()
return redirect('articles:index')
else:
form = PasswordChangeForm(request.user)
context = {
'form' : form,
}
return render(reqeust, 'accounts/change_password.html', context)
세션 무효화 방지하기
암호 변경 시 세션 무효화
- 비밀번호가 변경되면 기존 세션과의 회원 인증 정보가 일치하지 않게 되어 버려 로그인 상태가 유지되지 못하고 로그아웃 처리됨
- 비밀번호가 변경되면서 기존 세션과의 회원 인증 정보가 일치하지 않기 때문
update_session_auth_hash(request, user)
- 암호 변경 시 세션 무효화를 막아주는 함수
- 암호가 변경되면 새로운 password의 Session Data로 기존 session을 자동으로 갱신
from django.contrib.auth import update_session_auth_hash
def change_password(request, user_pk):
if request.method = 'POST':
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
user = form.save()
update_session_auth_hash(request, user)
return redirect('articles:index')
else:
form = PasswordChangeForm(request.user)
context = {
'form' : form,
}
return render(reqeust, 'accounts/change_password.html', context)
인증된 사용자에 대한 접근 제한
- is_authenticated 속성
- login_required 속성
is_authenticated
- 사용자가 인증되었는지 여부를 알 수 있는 User model의 속성
- 모든 User 인스턴스에 대해 항상 True인 읽기 전용 속성이며, 비인증 사용자에 대해서는 항상 False
<h1>회원가입</h1>
<form action="{% url 'accounts:signup' %}" method="POST">
{% csrf_token %}
{{form.as_p}}
<input type = "submit">
</form>
{% if reqeust.user.is_authenticated %}
<h3>Hello, {{user.username}} </h3>
<a href="{% url 'articles:create' %}">NEW</a>
<form action="{% url 'accounts:logout' %}" mehtod ="POST">
{% csrf_token %}
<input type="submit" value="Logout">
</form>
<form action="{% url 'accounts:delete' %}" mehtod ="POST">
{% csrf_token %}
<input type="submit" value="회원탈퇴">
</form>
<a href="{% url 'accounts:update' %}">회원정보 수정</a>
{% else %}
<a href="{% url 'accounts:login' %}">Login</a>
<a href="{% url 'accounts:signup' %}">Signup</a>
{% endif %}
login_required
- 인증된 사용자만 게시글을 작성/수정/삭제 할 수 있도록 수정
from django.contrib.auth.decorators import login_required
@login_required
def create(request):
pass
@login_required
def delete(request, article_pk):
pass
@login_required
def update(request, article_pk):
pass
@login_required
def change_password(request):
pass