티스토리 뷰

  ● 회원가입  

 

templates/base.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>{% block title %}{% endblock %} | Jihee's Blog</title>

  <!-- Google Font -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
  <!-- jQuery 3 -->
<script src="/static/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body class="hold-transition {% block page %}{% endblock %}-page">
{% block content %}
{% endblock %}
</body>
</html>

 

 

templates/register.html

{% extends 'base.html' %}
{% block title %}회원가입{% endblock %}
{% block page %}SIGN UP{% endblock %}

{% block content %}
<div style = "padding-left:50px; padding-top:50px;">
    <h1>Sign up</h1>
    <hr>
    <form action = "" method = "POST">
        {{user_form.as_p }}
        {% csrf_token %}
        <input class = "btn btn-primary" type = "submit" value = "submit">
    </form>
</div>
{% endblock %}

- user_form을 p 형태로 보여줌. p 말고도 as_table, as_ul 으로도 가능

 

 

 

user_form.as_p

 

 

 

user_form.as_table

 

 

 

user_form.as_ul

 

 

 

 

user/forms.py

from django import forms
from .models import User

class RegisterForm(forms.ModelForm):
    password = forms.CharField(label = 'password', widget = forms.PasswordInput)
    re_password = forms.CharField(label = 're_password', widget = forms.PasswordInput)

    class Meta:
        model = User
        fields = ['username', 'first_name', 'last_name', 'gender', 'email']

    def clean_re_password(self):
        cd = self.cleaned_data
        if cd['password'] != cd['re_password']:
            raise forms.ValidationError('비밀번호가 일치하지 않습니다.')
        
        return cd['re_password']

- ModelForm 을 상속받으면 class Meta 에서 모델과 필드만 지정해주면 자동으로 폼을 생성해준다.

- clean_re_password 함수를 통해서 비밀번호와 재입력 비밀번호의 일치 여부를 확인한다.

 

 

 

- 갑자기 궁금증

그런데 왜 password, re_password는 fields 에 써주지 않는걸까.. re_password는 사용자 모델 필드에 없는 값이라고 치지만 password는 왜 따로 빼주는걸까? 

그래서 그냥 다 주석처리하고 실행해봤는데 아래 사진처럼 password 부분이 암호화 처리 되지않은 상태로 출력된다. 비밀번호 재입력 비교와 비밀번호 암호화 처리를 위해서 따로 필드 값을 지정하는 것 같다. 

class RegisterForm(forms.ModelForm):
  class Meta:
        model = User
        fields = ['username', 'password', 'first_name', 'last_name', 'gender', 'email']

 

 

 

 

 

 

user/views.py

from django.shortcuts import render
from .forms import RegisterForm

def register(request):
    if request.method == 'POST':
        user_form = RegisterForm(request.POST)
        if user_form.is_valid():
            user = user_form.save(commit = False)
            user.set_password(user_form.cleaned_data['password'])
            user.save()
            return render(request, 'login.html', {'user':user})
    
    elif request.method == 'GET':
        user_form = RegisterForm()
    
    return render(request, 'register.html', {'user_form':user_form})

- POST 와 GET으로 나눠서 함수를 실행한다. GET 요청인 경우에는 그냥 Form을 띄워주고, POST 인 경우엔 전달받은 form의 유효성을 검사하고 DB에 저장한다.

 

- user_form.save(commit = False) 메소드는 바로 DB에 저장한다는 뜻이 아니라 DB 저장 여부를 Commit flag 값을 통해 확인한다. commit = False 인 경우, 함수 호출을 지연시켜서 DB에 중복으로 저장되는 것을 막는다. 

 

- set_password : 검증에 통과한 user_form.cleaned_data['password'] 값을 암호화하여 비밀번호 필드에 저장한다.

 

 

 

 

 

 

회원가입 실행 결과

 

RegisterForm 을 완성하고 submit 버튼을 누르면

 

 

admin 페이지에서 제대로 User 생성되었는지 알 수 있다.

위에서 사용자 정보를 입력한 그대로 저장되어서 생성되었다.

 

 

 

 

 

TypeError 에러 발생

 

(1) 오류 내용

if self.pattern.name is not None and ":" in self.pattern.name: TypeError: argument of type 'function' is not iterable

 

(2) 오류 해결

urls.py 에서  path('register/', register, name =  register)와 같이 적었다. 그런데 name 값에 string 처리를 하지 못해서 오류가 발생하는 것이었다. 왜 까먹었을까? 앞으로 까먹지 말자

path('register/', register, name = 'register')

댓글