241220 TIL 회원기능 구현하기

윤수용·2024년 12월 19일
0

TIL

목록 보기
83/89

1. 회원기능 구현하기

회원가입

  • Django의 기본 회원가입 ModelForm: UserCreationForm
    - usernamepassword로 새로운 user를 생성하는 ModelForm
    - username, password1, password2를 가짐

구현 결과

# accounts/urls.py
urlpatterns = [
    ...
    path("signup/", views.signup, name="signup"),
    ...
]
# accounts/views.py
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():
            user = form.save()  # 새로운 유저 회원가입 정보 저장 
            auth_login(request, user)  # 회원가입과 동시에 새 회원 정보로 로그인 
            return redirect("articles:index")
    else:
        form = UserCreationForm()
    context = {"form": form}
    return render(request, "accounts/signup.html", context)
<!-- accounts/signup.html -->
<h1>Sign up</h1>

<form action="{% url 'accounts:signup' %}" method="POST">
	{% csrf_token %}
	{{ form.as_p }}
	<button type="submit">Sign up</button>
</form>
<!-- base.html -->
...
 {% else %}
	<a href="{% url 'accounts:login' %}"><button>Login</button></a>
	<a href="{% url 'accounts:signup' %}"><button>Sign Up</button></a>
{% endif %}
...

회원탈퇴

  • DB에서 User를 지우는 로직
  • 회원 탈퇴 → 세션 삭제 순서에 유의

구현 결과

# accounts/urls.py
urlpatterns = [
    ...
    path("delete/", views.delete, name="delete"),
    ...
]
# accounts/views.py
@require_POST
def delete(request):
    if request.user.is_authenticated:
        request.user.delete()  # 회원 탈퇴 
        auth_logout(request)  # 세션 지우기 
    return redirect("articles:index")
<!-- base.html -->
{% if request.user.is_authenticated %}
	...
	<form action="{% url 'accounts:delete' %}" method="POST">
		{% csrf_token %}
		<input type="submit" value="Drop out"></input>
	</form>
{% else %}

정보 수정

  • Django의 기본 정보 수정 ModelForm: UserChangeForm
  • UserChangeForm을 사용하면 user가 수정하면 안될 정보까지 보임
    - 상속을 통해 UserChangeForm의 필요한 기능만 Form 커스텀
    - 커스텀한 Form의 이름 설정: CustomUserChangeForm

CustomUserChangeForm 만들기

  • get_user_model()
    - 현재 프로젝트에서 활성화 되어있는 유저모델을 반환
    - 직접 User 모델을 import 할 수 있지만 get_user_model 을 사용하기를 권장
    - Django는 다중 User 모델을 지원하므로 확장에 용이
    - 프로젝트의 유연성과 확장성을 높여줌

  • Class Meta의 fields에 들어갈 수 있는 값들: fields

구현 결과

# accounts/urls.py
urlpatterns = [
    ...
    path("update/", views.update, name="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 = [
            "first_name",
            "last_name",
            "email",
        ]
# accounts/views.py
from .forms import 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("articles:index")
    else:
        form = CustomUserChangeForm(instance=request.user)
    context = {"form": form}
    return render(request, "accounts/update.html", context)
<!-- accounts/update.html -->
<h1>Update Account</h1>

<form action="{% url 'accounts:update' %}" method="POST">
	{% csrf_token %}
	{{ form.as_p }}
	<button type="submit">Update</button>
</form>
<!-- base.html -->
{% if request.user.is_authenticated %}
	...
	<a href="{% url 'accounts:update' %}"><button>User Update</button></a>
	...
{% else %}

비밀번호 변경

  • Django의 기본 user 비밀번호 변경 ModelForm: PasswordChangeForm
  • 상속받고 있는 UserChangeForm을 보면, 비밀번호를 수정하는 경로를 미리 적어둠
    - 비밀번호 수정 경로를 커스텀하기 위해, 경로가 적힌 부분을 가져와 CustomUserChangeForm에서 Overriding
  • 비밀번호를 변경하면 기존 세션의 인증 정보와 일치하지 않아 자동으로 로그아웃 됨
    - update_session_auth_hash()함수를 사용해 로그인 상태를 유지

구현 결과

# accounts/urls.py
urlpatterns = [
    ...
    path("password/", views.change_password, name="change_password"),
    ...
]
# accounts/forms.py
from django.urls import reverse

class CustomUserChangeForm(UserChangeForm):
    class Meta:
        model = get_user_model()  # 현재 프로젝트에서 활성화 되어있는 유저를 반환 
        fields = [
            "first_name",
            "last_name",
            "email",
        ]
    
    #  비밀번호 수정 경로를 커스텀 할 수 있도록 UserChangeForm의 __init__을 Overriding
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.fields.get("password"):
            # reverse: url_name으로부터 url을 찾아가는 함수 
            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
# accounts/views.py
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import (
    AuthenticationForm,
    UserCreationForm,
    PasswordChangeForm,
)

@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("articles:index")
    else:
        form = PasswordChangeForm(request.user)
    context = {"form": form}
    return render(request, "accounts/change_password.html", context)
<!-- accounts/change_password.html -->
<h1>Change Password</h1>

<form action="{% url 'accounts:change_password' %}" method="POST">
	{% csrf_token %}
	{{ form.as_p }}
	<button type="submit">Change Password</button>
</form>
profile
잘 먹고 잘 살자

0개의 댓글