Django 사용자 정의 로그인 페이지 만들기

Woosang·2021년 9월 8일
0

django

목록 보기
1/2

사용자 정의 로그인 페이지


작업 flow

1. ModelForm생성하기(`forms.py`에서 작업)
	# django built in class 사용 `UserCreationForm`
for work in ['login', 'logout', 'register']:
	2. work의 view 생성하기(`views.py`에서 작업)
	# django의 `login`, `logout`, `authenticate` 사용	
	3. url mapping(`urls.py`에서 작업) -> view와 template을 연결하는 작업
	4. template(HTML) 작업

작업 순서는 본인이 편한대로
나의 경우 forms -> view -> urls -> template 순으로 작업

1. ModelForm생성


  • 일단 코드

  • 장고에서 제공하는 UserCreationForm을 상속 받아 사용
    - from django.contrib.auth.forms import UserCreationForm

  • 클래스 선언 후 Meta로 model과 사용할 fields설정
    - model의 경우 작업을 원하는 모델을 넣어준다.🔒

    • field의 경우 전부를 원한다면 '__all__', 특정 필드만 원한다면 위의 사진과 같이 리스트로 지정(14번째 줄), 일부를 빼고 나머지를 가져오고 싶으면 fields 변수대신 exclude = [빼고 싶은 필드명, ...]으로 지정한다.
  • 아래의 __init__() 메소드는 기본값을 커스텀하여 이쁘게 만들어준다.

  • 19번째 줄에 있는 self.fields는 위에서🔑(자물쇠 찾기) model변수에 넣어준 Model(지금의 경우 User)의 Fields들을 담고있다.

  • 해당하는 Field들을 한개씩 순회하면 속성(attrs)을 바꿔준다.(update) -> field.widget.attrs.update({'class':'input', ...})

  • init 커스텀 전 👆 커스텀 후 👇

Login page


2. view

  • 일단 코드
  • flow
    1. 만약 로그인된 상태로 접근하면 메인 페이지로 이동
    2. GET으로 접근하는 경우 render함수를 이용하여 login page로 이동
    3. POST로 접근하는 경우 request에서 username과 password를 추출 (장고 built in User모델에서는 아이디를 username으로 부름)
    4. 회원정보의 username이 있는지 확인, 없으면 예외처리 (장고 built in class message 사용)
    5. 장고에서 제공하는 인증 함수를 통해 아이디와 비밀번호가 맞는지 검증(authenticate)
      5-1. 만약 틀렸으면 authenticate함수는 null을 반환
    6. 인증이 성공했으면 장고의 login함수를 이용해 로그인시킨 후 redirect로 화면 이동

3. url mapping

from django.urls import path
from . import views

urlpatterns = [
    path('', views.profiles, name='profiles'),

    path('login/', views.login_user, name='login'),
    path('logout/', views.logout_user, name='logout'),
    path('register/', views.register_user, name='register'),

]

4. template 작업

  • 일단 코드 (나의 경우 조건절을 이용해 login과 register template을 하나로 처리)

  • 장고의 {{form.as_p}}를 사용해도 되지만 안예쁘니 태그로 꾸미기

logout page


2. view

  • 일단 코드
  • 장고의 logout을 이용해 로그아웃한다.

3. url mapping

from django.urls import path
from . import views

urlpatterns = [
    path('', views.profiles, name='profiles'),

    path('login/', views.login_user, name='login'),
    path('logout/', views.logout_user, name='logout'),
    path('register/', views.register_user, name='register'),

]

4. template 작업

  • 이 친구는 따로 template이 필요 없음

Register page


2. view

  • 일단 코드
  1. 1에서 생성한 ModelForm을 form에다 넣어준다.
  2. 나의 경우 login_register.html 한번에 처리하기 때문에 template에 넘겨줄 page를 설정해준다.(page = 'register')🔒
  3. GET으로 접근하면 form과 page와 함께 login_register.html로 이동
  4. POST로 접근하면 1에서 생선한 CustomUserCreationForm의 인수로 request.POST를 넣어 form에 담아준다.
  5. .is_valid()함수로 검증한다.(형식이 맞으면 True 반환)
  6. user라는 변수에 form을 담으면서 1차?저장한다 commit을 False로 지정하면 아직 DB에 반영X
  7. username을 소문자로 통일해준다.
user.username = user.username.lower()
  1. 소문자로 바꾸고 저장, 로그인, 이동(나의 경우 다른 곳으로 이동하기 위해 임시적으로 #으로 지정).

3. url mapping

from django.urls import path
from . import views

urlpatterns = [
    path('', views.profiles, name='profiles'),

    path('login/', views.login_user, name='login'),
    path('logout/', views.logout_user, name='logout'),
    path('register/', views.register_user, name='register'),

]

4. template 작업

  • 일단 코드

  • register로 접근하기 위해 첫번째 줄에 조건절로 시작(🔑위에 자물쇠 참고, 여기서 변수사용)

  • 넘겨받은 form을 한개씩 순회하며 양식을 채운다.

  • 만약 양식이 제대로 채워지지 않은 경우(비밀번호와 비밀번호 확인이 일치하지 않는 등) error를 확인하기 위해 field.error를 사용하여 명시적으로 보여준다.

template의 전체 코드

{% extends 'main.html' %}
{% load static %}

{% block content %}

{% if page == 'register' %}
<div class="auth">
    <div class="card">
        <div class="auth__header text-center">
            <a href="/">
                <img src="{% static 'images/icon.svg' %}" alt="icon" />
            </a>
            <h3>회원가입</h3>
            <p>Create a new developer account</p>
        </div>

        <form action="{% url 'register' %}" method="POST" class="form auth__form">
            {% csrf_token %}

            {% for field in form %}
            <div class="form__field">
                {% if field.label == '사용자 이름' %}
                    <label for="formInput#text">아이디</label>
                {% else %}
                    <label for="formInput#text">{{field.label}}</label>
                {% endif %}
                {{field}}

                {% for error in field.errors %}
                    <p style="color: red;">{{error}}</p>
                {% endfor %}
            </div>
            {% endfor %}

            <div class="auth__actions">
                <input class="btn btn--sub btn--lg" type="submit" value="Sign in">
            </div>
        </form>
        <div class="auth__alternative">
            <p>Already have an Account?</p>
            <a href="{% url 'login' %}">Log In</a>
        </div>
    </div>
</div>
{% elif page == 'login' %}
<div class="auth">
    <div class="card">
        <div class="auth__header text-center">
            <a href="/">
                <img src="{% static 'images/icon.svg' %}" alt="icon">
            </a>
            <h3>로그인</h3>
            <p>Hello Developer, Welcome Back!</p>
        </div>

        <form class="form auth__form" action="" method="POST">
            {% csrf_token %}
            <!-- Input:Username -->
            <div class="form__field">
                <label for="formInput#text">아이디 :</label>
                <input class="input input--text" id='formInput#text' type="text"
                    name="username" placeholder="Enter your ID">
            </div>
            <!-- Input:Password -->
            <div class="form__field">
                <label for="formInput#password">비밀번호 :</label>
                <input class="input input--password" id="formInput#password" type="password"
                    name="password" placeholder="••••••••">
            </div>

            <div class="auth__actions">
                <input class="btn btn--sub btn-0lg" type="submit" value="Log in">
                <a href="#">Forget Password?</a>
            </div>
        </form>

        <div class="auth__alternative">
            <p>Don't have an Account?</p>
            <a href="{% url 'register' %}">회원가입</a>
        </div>
    </div>
</div>
{% endif %}

{% endblock content %}

0개의 댓글