웹 프로그래밍/[ Django ]

[ Django ] 04. Django 로그인/회원가입 구현

kim.svadoz 2020. 8. 11. 09:49
728x90
반응형

Django 로그인 /회원가입

회원가입

# urls.py
path('signup/', views.signup, name="signup"),

# views.py
from django.contrib.auth.forms import UserCreationForm

# Create your views here.
def signup(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            return redirect('articles:index')
    else:
        form = UserCreationForm()
    context = {
        'form' : form
    }
    return render(request, 'accounts/signup.html', context)

# signup.html
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block body %}
<h1>회원가입</h1>
<form action="" method="POST">
  {% csrf_token %}
  {% bootstrap_form form %}
  {% buttons %}
    <button type="submit" class="btn btn-primary">
      Submit
    </button>
  {% endbuttons %}
</form>

{% endblock %}

로그인

# urls.py
path('login/', views.login, name="login"),

# views.py
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login as auth_login

def login(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, request.POST)
        # AuthenticationForm은 ModelForm이 아닌 Form을 상속하기 때문에 생긴게 달라진다.
        # 별도로 정의된 Model이 없다는 뜻 => 고로 넘겨주는 인자가 달라진다.
        if form.is_valid():
            # 로그인은 DB에 뭔가 작성하는 것은 동일하지만 연결된 모듈이 있는 것은 아니다.
            # 그럼 확인해야 하는것은????
            #   => 세션과 유저정보를 확인해야 하기때문에
            #   => 세션(request)와 유저정보(form.get_user())를 확인해야 한다.
            auth_login(request, form.get_user())
            return redirect(request.GET.get('next') or 'articles:index')
    else:
        form = AuthenticationForm
    context={
        'form' : form
    }
    return render(request, 'accounts/login.html', context)

# login.html
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block body %}
<h1>로그인</h1>
<form action="" method="POST">
  {% csrf_token %}
  {% bootstrap_form form %}
  {% buttons %}
    <button type="submit" class="btn btn-primary">
      Submit
    </button>
  {% endbuttons %}
</form>

{% endblock %}

로그아웃

# urls.py
path('logout/', views.logout, name="logout"),

# views.py
from django.contrib.auth import logout as auth_logout
def logout(request):
    auth_logout(request)
    return redirect('articles:index')

# base.html
{% load bootstrap4 %}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  {% bootstrap_css %}
  <title>Document</title>
</head>
<body>
  <h1>{{ user.username }}</h1>

  {% if user.username == "" %}
  <a href="{% url 'accounts:login' %}">login</a>
  {% else %}
  <a href="{% url 'accounts:logout' %}">logout</a>
  {% endif %}
  <div class="container">
    {% block body %}
    {% endblock %}
  </div>
  {% bootstrap_javascript jquery='full' %}
</body>
</html>

image-20200623130701596

user가 anonymous일때는 항상 false를 리턴.

from IPython import embed

def index(request):
    embed()
    ...

#shell
request.user

# 로그인 안했을 시
request.user.is_anonymous
-> True

request.user.is_authenticated
-> False

# 로그인 안했을 시
request.user.is_anonymous
-> False

request.user.is_authenticated
-> True

shell 창에서 request를 출력해보면 anonymous가 들어있는 것을 확인할 수 있음.

*따라서 다음과 같이 base.html의 조건문을 변경해주는게 좋다 *

{% if user.is_authenticated %}
<a href="{% url 'accounts:login' %}">login</a>
{% else %}
<a href="{% url 'accounts:logout' %}">logout</a>
{% endif %}

=> 세션에 접근을 해서 통과를 해 정보를 가져와서 무엇을 하는 게 아니라 단지 로그인했는지만 체크하는것

템플릿에서 user를 쓸 수 있는 이유는 우리가 항상 request를 보내주기 때문이다.

로그인/비로그인 페이지 분할

ex ) 네이버와 구글의 로그인 페이지

  • 로그인이 되어있는데도 또 로그인 페이지 접근을 시도하면 index페이지로 redirect시키기(회원가입도)
###### 회원가입 하자마자 로그인 하기 위한 로직 추가
def signup(request):
    if request.user.is_authenticated:
        return redirect('articles:index')
    else:
        if request.method == 'POST':
            form = UserCreationForm(request.POST)
            if form.is_valid():
                user = form.save()
                ##### VVVVVVV
                auth_login(request, user)
                return redirect('articles:index')
        else:
            form = UserCreationForm()
        context = {
            'form' : form
        }
    return render(request, 'accounts/signup.html', context)

def login(request):
    if request.user.is_authenticated:
        return redirect('articles:index')
    else:
        if request.method == 'POST':
            form = AuthenticationForm(request, request.POST)
            # AuthenticationForm은 ModelForm이 아닌 Form을 상속하기 때문에 생긴게 달라진다.
            # 별도로 정의된 Model이 없다는 뜻 => 고로 넘겨주는 인자가 달라진다.
            if form.is_valid():
                # 로그인은 DB에 뭔가 작성하는 것은 동일하지만 연결된 모듈이 있는 것은 아니다.
                # 그럼 확인해야 하는것은????
                #   => 세션과 유저정보를 확인해야 하기때문에
                #   => 세션(request)와 유저정보(form.get_user())를 확인해야 한다.
                auth_login(request, form.get_user())
                return redirect(request.GET.get('next') or 'articles:index')
        else:
            form = AuthenticationForm
        context={
            'form' : form
        }
    return render(request, 'accounts/login.html', context)
from django.contrib.auth.decorators import login_required
  • articles app 에 있는 detail, index 제외한 모든 함수에 @login_required를 붙여준다...

image-20200623140626122

=> login이 안된상태에서 create버튼을 누르면 login페이지로 넘어간다.

회원 탈퇴

먼저 @require_POST를 사용하기 위해 import해주는 작업

from django.views.decorators.http import require_POST
# urls.py
path('delete/', views.delete, name="delete"),

# views.py
# @login_required가 있으면 페이지405 오류가 뜬다. 따라서 GET방식 뭐시기
@require_POST
def delete(request):
    request.user.delete()
    return redirect('articles:index')

# base.html
{% if user.is_authenticated %}
  <a href="{% url 'accounts:logout' %}"><h5>logout</h5></a>
  <form action="{% url 'accounts'delete %}" method='POST'>
    {% csrf_token %}
    <input type="submit" value="회원 탈퇴">
  </form>
  {% else %}
  <a href="{% url 'accounts:login' %}"><h5>login</h5></a>
  <a href="{% url 'accounts:signup' %}"><h5>[회원가입]</h5></a>
{% endif %}

회원수정

# urls.py
path('update/', views.update, name="update"),

# views.py
from .forms import CustomUserChangeForm
@login_required
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)

# base.html
<a href="{% url 'accounts:update' %}">회원 수정</a>
  • UserChangeForm 커스터마이징
# 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']

비밀번호 수정

from django.contrib.auth.forms import PasswordChangeForm
# urls.py
path('password/', views.password, name="password"),

# views.py
@login_required
def password(request):
    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            user = form.save()
            auth_login(request, user)
            return redirect('articles:index')
    else:
        form = PasswordChangeForm(request.user)
    context = {
        'form' : form
    }
    return render(request, 'accounts/password.html', context)
  • 비밀번호 수정 후에도 세션을 유지시키기 위한 작업
from django.contrib.auth import update_session_auth_hash

@login_required
def password(request):
    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(request, 'accounts/password.html', context)

=> 눈에 보이지 않는 세션 값이 기존과 그대로 유지한다.

728x90
반응형