Django - 회원가입

Lee Ju-Hyeon(David)·2021년 9월 16일
0

Django

목록 보기
10/10
post-thumbnail

UserCreationForm

  • 권한이 없는 새 user를 생성하는 ModelForm이다
  • username, password1, password2 세 개의 필드를 가진다.
# django github 발췌
class UserCreationForm(forms.ModelForm):
    """
    A form that creates a user, with no privileges, from the given username and
    password.
    """
    error_messages = {
        'password_mismatch': _('The two password fields didn’t match.'),
    }
    password1 = forms.CharField(
        label=_("Password"),
        strip=False,
        widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
        help_text=password_validation.password_validators_help_text_html(),
    )
    password2 = forms.CharField(
        label=_("Password confirmation"),
        widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
        strip=False,
        help_text=_("Enter the same password as before, for verification."),
    )

1. 회원가입

url설정을 한 뒤, view 함수에 회원가입을 위한 UserCreationForm을 랜더링 해주었다.
사용자 이름, 비밀번호, 비밀번호 확인 세 가지 필드가 있는 것이 보인다.

UserCreationForm 커스텀

사용자의 이름, 이메일 등의 정보를 추가로 받기 위해 UserCreationForm을 상속 받은 새로운 Form을 forms.py에 정의해야 한다.

#accounts/forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import get_user_model


class CustomUserCreationForm(UserCreationForm):

    class Meta:
        model = get_user_model()
        fields = UserCreationForm.Meta.fields + ('eamil', 'first_name', 'last_name')
        # fields = ('username',)

modelget_user_model()을 사용한다. get_user_model()은 최근에 활성화된 User model을 반환하는 것으로, Django에서는 User 클래스를 직접 참조하기 보다는 get_user_model()을 사용해 참조하는 것을 추천하며 강조한다.

fields에는 UserCreationForm에서 기존에 페이지에 랜더링해주던 정보 이외에 이메일과 이름을 저장하는 필드를 추가했다.사진은 Django의 UserCreationForm의 정의로 User라는 것을 모델로 사용하고 있다.User라는 클래스는 다시 AbstractUser를 상속받고 있다AbstractUser를 보면 우리가 사용하려고 하는 이메일과 이름 필드가 정의되어 있다. CustomUserCreationForm에서 UserCreationForm을 상속 받고 있기 때문에 새롭게 필드를 정의할 필요없다.ID와 비밀번호 외에 이름과 이메일을 작성하는 부분이 추가되었다.

회원가입, 가입 후 바로 로그인 처리

@require_http_methods(['GET', 'POST'])
def signup(request):
    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            auth_login(request, user)
            return redirect('records:index')redirect('records:index')
    else:
        form = CustomUserCreationForm()
    context = {
        'form': form,
    }
    return render(request, 'accounts/signup.html', context)

create함수와 매우 유사하다. 이유는 회원가입도 한 명의 유저 데이터를 데이터베이스에 추가하는 동작이기 때문이다. 회원가입을 진행하면 유저정보가 잘 추가된 것을 볼 수 있다.

login함수는 두 번째 인자로 user의 데이터를 필요로 하는데, 로그인을 구현할 때 get_user()메서드를 사용했다. 하지만 여기서는 save()메서드를 사용한 뒤 반환값을 user에 저장하여 사용한다. 이게 가능한 이유는 save()메서드의 정의를 보면 알 수 있다.UserCreationForm의 save()메서드를 보면 user 정보를 반환하는 것을 볼 수 있다. 따라서 save()메서드의 반환값을 저장하면 유저 정보를 사용할 수 있다.


2. 회원탈퇴

user가 저장된 데이터베이스에서 해당 유저 정보를 삭제하는 작업이므로 Delete와 유사하다.

@require_POST
def delete(request):
    if request.user.is_authenticated:
        request.user.delete()
    return redirect('records:index')

로그인되어 있는 상태에서 POST 요청이 오면 데이터베이스에서 user 정보를 삭제하고 메인 페이지로 redirect 한다.회원탈퇴를 했지만, 로그아웃을 한 게 아니기 때문에 세션은 그대로 남아있다. 세션까지 삭제하고 싶다면 삭제 후에 로그아웃을 하면 된다.


3. 회원 정보 수정

UserChangeForm

# django github 발췌
class UserChangeForm(forms.ModelForm):
    password = ReadOnlyPasswordHashField(
        label=_("Password"),
        help_text=_(
            'Raw passwords are not stored, so there is no way to see this '
            'user’s password, but you can change the password using '
            '<a href="{}">this form</a>.'
        ),
    )

    class Meta:
        model = User
        fields = '__all__'
        field_classes = {'username': UsernameField}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        password = self.fields.get('password')
        if password:
            password.help_text = password.help_text.format('../password/')
        user_permissions = self.fields.get('user_permissions')
        if user_permissions:
            user_permissions.queryset = user_permissions.queryset.select_related('content_type')

UserChangeForm을 이용해서 페이지를 랜더링하면 아래와 같이 된다.불필요한 정보가 많이 노출되고 있다. UserCreationForm을 더 필요한 정보를 추가하기 위해 커스텀한 것처럼 UserChangeForm도 불필요한 정보 노출을 줄이기 위해 커스텀이 필요하다.

UserCreationForm 커스텀

#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 = ('email', 'first_name', 'last_name')

필요한 필드만 정의해서 Form 정의했다.

회원 정보 수정

@require_http_methods(['GET', 'POST'])
def update(request):
    if request.method == 'POST':
        form = CustomUserChangeForm(request, instance=request.user)
        if form.is_valid():
            form.save()
            return redirect('records:index')
    else:
        form = CustomUserChangeForm(instance=request.user)
    context = {
        'form': form
    }
    return render(request, 'accounts/update.html', context)

현재 유저에 대한 정보를 가진 CustomUserChangeForm 인스턴스를 만들고 유효성 검사를 진행한다. 그 다음 유저가 입력한 정보를 저장하고 메인 페이지로 redirect한다.회원 정보가 수정되었다.


4. 비밀번호 변경

회원 정보 수정 페이지로 들어가면 위의 사진의 문구를 볼 수 있다.

PasswordChangeForm

사용자가 비밀번호를 변경할 수 있도록 하는 Form으로 SetPassowrdForm을 상속 받는다.


비밀번호 변경, 변경 후 로그인 유지 처리

def change_password(request):
    if request.method == "POST":
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            form.save()
            return redirect('records:index')
    else:
        form = PasswordChangeForm(request.user)
    context = {
        'form': form,
    }
    return render(request, 'accounts/change_password.html', context)

Update와 유사한 구조를 가지고 있다. 그런데 UserChangeForm이나 UserCreationForm과 달리 PasswordChangeForm은 첫번째 인자로 유저 정보를 받고 있다. 이는 SetPassowrdForm을 상속 받고 있기 때문이다. SetPassowrdForm의 생성자 함수는 user정보를 첫 인자로 받는다.

비밀 번호를 변경하고 나면 메인 페이지로 이동함과 동시에 로그인이 해제된다. 즉, 로그인 세션이 비밀번호 변경 전과 일치하지 않는다.

update_session_auth_hash를 이용하면 비밀번호 변경 시 새로운 비밀번호 해시를 이용해 Session을 업데이트할 수 있다.

update_session_auth_hash(request, form.user)

PasswordChangeForm은 SetPassowrdForm을 상속받고 user정보를 첫 인자로 전달 받기 때문에 user정보를 가지고 있다.

수정 전수정 후

비밀번호 변경 전후를 보면 session_id가 달라진 것을 볼 수 있다.

0개의 댓글