강의 링크: Learn Django by Building an Online Marketplace – Python Tutorial for Beginners
# forms.py 파일 추가하기
{project}/core 폴더 하위에 forms.py 파일을 추가한다. 장고 프로젝트에서 forms.py 파일은 사용자 입력을 처리하고, 이를 기반으로 데이터를 검증하는 데 사용한다.
forms.py에는 모델을 선언하는 것과 비슷한 방식으로 폼을 선언한다. from django import forms 구문을 통해 폼 라이브러리를 가져와서 직접 필드를 생성해도 되고, 아니면 django.contrib.auth.form 패키지에 있는 UserCreationForm이라는 장고에 내장된 회원가입용 폼을 사용해도 된다. 튜토리얼 영상에선 후자의 방법으로 진행을 해서 아래와 같이 작성했는데, 전자의 방식으로 진행하고 싶을 경우 MDN 튜토리얼을 참고하면 좋을 것 같다.
# forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignupForm(UserCreationForm): # UserCreationForm을 상속 받는 SignupForm 정의
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
# 회원가입 뷰 추가하기
{project}/core/views.py에 다음과 같이 회원가입 뷰를 추가해주는데, 먼저 방금 만든 폼을 불러와 인스턴스를 생성한 뒤(19번째 줄), render의 인자에 form이라는 이름으로 넘겨준다.(21~12번째 줄)
그러면 signup.html에서 다음과 같이 form이라는 변수로 폼을 받아서 사용할 수 있다.
{% extends "core/base.html" %}
{% block title %}
Signup
{% endblock title %}
{% block content %}
{{ form }}
{% endblock content %}
위와 같이 form을 통째로 뿌려버리면 화면 상에선 어떻게 보여질까?
위 그림과 같이, forms.py에서 폼 선언할 때 fields 값으로 넘겨준 4가지 필드가 각각 label 태그와 input 태그의 쌍으로 엮여서 나타난다. 그런데 아무래도 스타일도 구리고 form 태그로 감싸져 있지도 않아서 이대로 사용하는 건 무리인 것 같다. 다음과 같이 폼의 각 필드를 개별적으로 받아와서 커스텀해서 보여주도록 하자.
{% extends "core/base.html" %}
{% block title %}
Sign up
{% endblock title %}
{% block content %}
<div class="w-1/2 my-6 mx-auto p-6 bg-gray-100 rounded-xl">
<h1 class="mb-6 text-3xl text-center">Sign up</h1>
<form method="post" action=".">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="mb-3">
<label class="inline-block mb-2">Username</label>
<br>
{{ form.username }}
</div>
</form>
</div>
{% endblock content %}
*위 예시와 같이 내부 URL로 처리되는 POST form 태그의 경우, CSRF 방지를 위해 내부에 {% csrf_token %} 템플릿 태그를 꼭 넣어줘야 한다. (참고: https://docs.djangoproject.com/en/1.8/ref/csrf/)
*non_field_errors는 특정 필드에서의 에러가 아닌, 폼 자체의 논리적 검증 실패로 인해 발생하는 에러가 발생하는 경우에 대응하기 위해 사용한다. (예: Password와 Password Confirm이 비밀번호 정규식은 통과하지만 서로 불일치하는 경우)
그러면 위와 같이 폼의 특정 필드(여기선 username)의 input 태그만 보여줄 수 있다.
# input 커스터마이징
다음과 같이 장고 폼 라이브러리의 CharField 클래스를 통해 각 input을 커스터마이징할 수 있다.
실습에선 tailwind를 사용하고 있기 때문에, 위와 같이 class attribute에 tailwind의 클래스들을 전달하여 스타일링 하면 된다.
# 폼 제출을 처리하는 로직 추가
forms.py에 다음과 같이, 사용자가 폼을 제출할 때, 즉 signup 뷰에서 POST 요청이 들어올 때에 대한 처리를 추가해준다.
messages.success()는 장고의 messages 프레임워크를 사용하여 사용자에게 회원가입이 정상적으로 처리되었다는 메시지를 보여주기 위해 추가해두었다.
from django.shortcuts import render, redirect
from django.contrib import messages
from item.models import Category, Item
from .forms import SignupForm
# ........중략
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
user = form.save() # 폼 데이터를 DB에 저장
messages.success(request, f"Welcome, {user.username}! Your account has been created.")
return redirect('/login/')
else:
form = SignupForm()
return render(request, 'core/signup.html', {
'form': form
})
def login(request):
return render(request, 'core/login.html')
회원가입 완료 후 사용자를 로그인 페이지로 리다이렉트 시키면 다음과 같이 메시지 박스와 메시지를 보여주고자 한다.
우리가 아까 messages.success()를 통해 저장한 메시지를 위와 같이 보여주기 위해선, 템플릿 상에서 messages 변수를 통해 메시지를 꺼내와야 한다. (아래 코드블럭 참고) 메시지 박스는 다음과 같이 base.html에 추가해두었는데, 이렇게 하면 로그인 페이지 뿐만 아니라 어떠한 페이지에서든 메시지 스토리지에 메시지가 있으면 사용자에게 메시지를 보여주게 된다.
<!--base.html-->
{% if messages %}
<ul class="w-full flex justify-center">
{% for message in messages %}
<li class="w-11/12 py-3 px-6 my-10 rounded-md bg-teal-50 border-teal-500 border">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<div class="px-6 py-6">
{% block content %}
{% endblock content %}
</div>
form.save()를 통해 DB에 저장했던 회원가입 정보는 다음과 같이 어드민 페이지에서 확인할 수 있다.
'학습 내용 > Back-End' 카테고리의 다른 글
[freeCodeCamp] Django로 쇼핑몰 만들기 실습 - 6. SQLite (1) | 2024.12.10 |
---|---|
[freeCodeCamp] Django로 쇼핑몰 만들기 실습 - 5. 로그인 기능 (0) | 2024.12.04 |
[freeCodeCamp] Django로 쇼핑몰 만들기 실습 - 3. 어드민 페이지 (1) | 2024.11.25 |
[freeCodeCamp] Django로 쇼핑몰 만들기 실습 - 2. 뷰(view) 만들기 (0) | 2024.11.24 |
[freeCodeCamp] Django로 쇼핑몰 만들기 실습 - 1. 프로젝트 생성하기 (0) | 2024.11.22 |