Meme's IT

[Django] 로그인(2) 가입/탈퇴/수정 본문

BackEnd/Django

[Django] 로그인(2) 가입/탈퇴/수정

Memez 2023. 10. 5. 11:10

2023.10.04 - [Django] - [Django] 로그인(1) 로그인, 로그아웃

 

[Django] 로그인(1) 로그인, 로그아웃

# Django Authentication System 사용자 인증과 관련된 기능을 모아 놓은 시스템 이 기능을 통해, 로그인 / 로그아웃을 구현할 수 있다. # 사전 작업 0. https://memezz.tistory.com/24에서 작성한 프로젝트에서 이

memezz.tistory.com

 

앞의 글과 이어집니다.


# 회원가입 구현하기

회원가입 = User 객체를 Create하는 과정

 

회원 가입시, 사용자 입력 데이터를 받는 built - in ModelForm인 UserCreationForm()을 이용

 

1. 기본적인 페이지 만들기

# accounts/urls.py

app_name = 'accounts'
urlpatterns = [
    path('login/', views.login, name='login'),
    path('logout/', views.logout, name='logout'),
    path('signup/',views.signup,name='signup'),		# 추가
]
# accounts/views.py

from django.contrib.auth.forms import UserCreationForm


def signup(request):
    if request.method == "POST":
        pass
    else:
        form = UserCreationForm()
    context = {
        'form':form,
    }
    return render(request,'accounts/signup.html',context)
<!-- signup.html -->

<h1>회원가입</h1>
<form action="{% url "accounts:signup" %}" method="POST">
    {% csrf_token %}
    {{form.as_p}}
    <input type="submit">
</form>

 

 

회원가입 페이지 틀 완성

 

2. signup함수에 회원가입 로직 넣기(유효성 검사 + DB에 등록)

# accounts/views.py

def signup(request):
    if request.method == "POST":
        form = UserCreationForm(request.POST)
        if form.is_valid():		# 입력이 유효하다면
            user = form.save()		# DB에 등록
            auth_login(request,user)	# 로그인도 바로 해주기
            return redirect('articles:index')	# 회원가입이 완료된다면, 메인페이지로 넘어가기
    else:
        form = UserCreationForm()
    context = {
        'form':form,
    }
    return render(request,'accounts/signup.html',context)

 

함수를 수정한 후, 회원가입을 진행하면

다음과 같은 오류가 발생한다.

왜냐하면..

위에서 사용한 UserCreationForm에서 사용되는 User와

우리가 만든 User가 서로 다르기 때문

+ 이후 회원 정보 수정에서 쓰는 UserChangeForm도 똑같다

더보기

UserCreationForm의 유저는 원래 존재하던 auth_User이다

https://github.com/django/django/blob/main/django/contrib/auth/forms.py#L84

 

그럼 어떡하지..

커스텀 유저 모델을 작성해주자( = Form을 만들자)

 

 

3. 커스텀 Form 만들기(회원정보 수정용 UserChangeForm도 동시에 해줌)

accounts폴더에 forms.py 파일 생성 및 작성

from django.contrib.auth.forms import UserCreationForm, UserChangeForm
# 회원가입 / 수정을 위한 모델을 모두 import해줌
from django.contrib.auth import get_user_model 	# 현재 내가 만든 User도 import해줌

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는 뭐지?

그냥 from .model import User으로 내가 만들어 온 User을 가져오면 안될까?

→ 그렇게 하면 나중에 User의 이름이 바뀌거나, 수정사항이 생기면 일일히 다 바꿔줘야 함

이걸 위해서 Django에서 제공하는 get_user_model을 이용해서

현재 프로젝트에서 활성화된 유저 모델을 반환해준다.

(+ 유지보수에도 매우 좋다!)

 

이후, UserCreationForm이 사용되었던 views.py위치의 signup함수 수정

from .forms import CustomUserCreationForm, CustomUserChangeForm	
# 작성해둔 form에서 가져오기

def signup(request):
    if request.method == "POST":
        form = CustomUserCreationForm(request.POST)	# 수정
        if form.is_valid():
            user = form.save()
            auth_login(request,user)
            return redirect('articles:index')
    else:
        form = CustomUserCreationForm()	# 수정
    context = {
        'form':form,
    }
    return render(request,'accounts/signup.html',context)

 

이후 회원가입을 하면, 로그인이 되고 index 페이지로 넘어가는 것을 확인할 수 있다.


# 회원 탈퇴 구현하기

회원 탈퇴 = User 객체를 Delete하는 과정

탈퇴는 매우 간단하다! 

요청하는 user의 정보를 가져와서 지우기만 하면 됨 → DB를 수정하므로 POST방식

+ 따로 html 파일도 필요 없음

# accounts/urls.py 추가

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

def delete(request):
    # 유저객체가 어디에 있는가?
    # 요청에 이미 유저 정보가 있다 → 그걸 지우면 됨
    request.user.delete()	# 데이터를 지우고
    auth_logout(request)	# 로그아웃까지 해줌
    return redirect('articles:index')	# 이후, 메인페이지로 redirect

탈퇴 버튼은 index, 즉 메인페이지에 버튼으로 구현해주기 위해 index.html에 추가

<!-- article/index.html -->

<form action="{% url "accounts:delete" %}" method="POST">
  {% csrf_token %}
  <input type="submit" value='탈퇴하기'>
</form>

'탈퇴하기'가 생성됨


# 회원정보 수정하기

회원정보 수정 = User 객체를 Update하는 과정

 

회원정보 수정 시 사용자 입력 데이터를 받을 built - in ModelFormUserChangeForm()을 이용

→ 이전에 회원 가입에서 form으로 CustomUserChangeForm을 생성해 둠, 그거 쓸꺼임

 

urls.py에 추가, views.py에 함수 새로 작성, Template 만들어 주기

# accounts/urls.py

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'),
    path('update/',views.update,name='update'),
]
def update(request):
    if request.method == "POST":
        form = CustomUserChangeForm(request.POST, instance=request.user)
        # instance는 수정이기 때문에, 원래의 데이터가 나오도록 하는 역할
        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)
<!-- Templates/accounts/update.html -->

<h1>회원정보수정</h1>
<form action="{% url "accounts:update" %}" method="POST">
    {% csrf_token %}
    {{form.as_p}}
    <input type="submit" value="수정하기">
</form>

+ 메인페이지에도 회원정보 수정을 할 수 있는 링크 생성

<a href="{% url "accounts:update" %}">회원정보수정</a>

다음과 같이 메인페이지에서도 회원정보 수정을 할 수 있다.

근데 회원정보 수정을 들어가보면,

뭔가 엄청 많다...

심지어 superuser가 될 수있는 체크박스도 있고...

그래서 이런걸 해결하기 위해서 form에서 출력할 항목을 정해줘야함

 

# accounts/forms.py 수정

class CustomUserChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = get_user_model()
        fields = ('first_name', 'last_name', 'email')