본문 바로가기
파이썬 웹 서비스 만들기

5. 계정 관리 페이지 - 5.3. 계정 삭제 기능

by 영바이트 2020. 10. 17.

계정 정보 수정을 위한 모델/폼-뷰-로직 요소들을 만들어 보았다. 같은 실습 프로젝트 04_user_page에 기능을 하나 더 추가할 것이다. 바로 계정을 삭제하는 기능이다. 접속한 사용자 입장에서 본다면 '탈퇴'버튼이라고 할 수 있다.

 

5.3.1. 입력 정보(모델/폼) 정의

 

계정을 삭제할지(=탈퇴할지) 확인(confirm)하기 위해 로그인 암호를 다시 한번 입력받는다. 대상이 되는 계정 정보는 이미 DB에 저장되어 있는 그것이다. 따라서 추가로 모델(DB에 저장될 정보의 종류와 형태)을 정의할 필요는 없고 입력받을 정보인 폼(DeleteAccountForm)만 정의하면 된다.

 

▶ appmain/user/forms.py

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from flask_wtf.file import FileField, FileAllowed
from appmain.user.models import Userdata

class RegistrationForm(FlaskForm):
####    ...
####    생략
####    ...

class UpdateAccountForm(FlaskForm):
####    ...
####    생략
####    ...

class DeleteAccountForm(FlaskForm):
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Confirm')

 

 

5.3.2. 입력 페이지(뷰) 구성

 

먼저 계정 정보 수정페이지 가장 아래에 '계정 삭제' 버튼을 추가하였다.

 

계정삭제(Delete) 버튼

 

▶ appmain/templates/account.html

{% extends "layout.html" %}
{% block content %}
<div>
    <!-- 현재 프로필 사진을 보여준다 -->
    <!-- 내용 생략 -->
    <!-- -->
    
    <!-- 이름(username), 이메일(email), 프로필 사진을 입력할 수 있는 필드들 -->
    <!-- 내용 생략 -->
    <!-- -->
    
    <!-- 계정 삭제 버튼 추가 -->
    <form method="POST" action="{{url_for('user.deleteAccount')}}">
        <span>
            <button type="submit">Delete</button>
        </span>
    </form>
    <!-- -->
</div>
{% endblock content %}

 

계정 정보 수정페이지의 '계정 삭제' 버튼을 클릭하면 로그인 암호를 다시 한번 물어보게하였다. 로그인 암호를 다시 한번 입력하고 '계정 삭제 확인(confirm deletion)' 아래의 버튼을 클릭하면 실제 계정 삭제 로직이 실행된다.

 

계정 삭제를 위한 암호 재입력 페이지

 

▶ appmain/templates/deleteAccount.html

{% extends "layout.html" %}
{% block content %}
<div>
    <p>
        Username: {{user.username}}<br/>
        User email: {{user.useremail}}
    </p>
    <form method="POST" action="">
        {{form.hidden_tag()}} {# Transferring CSRF token = secret key #}
        
        <!-- 계정 삭제 확인을 위해 암호를 다시 한번 입력한다. -->
        <p>Please enter your login password.</p>
        {{form.password}}
        <p>Confirm deletion?</p>
        {{form.submit}}
    </form>
</div>
{% endblock content %}

 

 

5.3.3. 계정 삭제 로직

 

계정 삭제 로직은 아래 두 가지 기능을 수행한다.

① 사용자가 계정 삭제 페이지 URL에 접속하면 계정 삭제 페이지를 제공한다.

② 사용자가 계정 삭제 확인 버튼을 클릭하면 서버에서 계정 정보를 삭제한다.

 

사용자 관리 기능의 일부이므로 user 패키지 아래 로직 파일(routes.py)에 작성하였다.

 

 

▶ appmain/user/routes.py

from flask import render_template, url_for, redirect, request, Blueprint
from appmain.user.forms import RegistrationForm
from appmain.user.models import Userdata
from appmain import app, db, bcrypt
from flask_login import current_user

from appmain.user.forms import LoginForm
from flask_login import login_user, logout_user

import os
import secrets
from PIL import Image
from appmain.user.forms import UpdateAccountForm
from flask_login import login_required

#### 계정 삭제를 위해 암호를 재입력하는 페이지에 쓰일 폼 추가
from appmain.user.forms import DeleteAccountForm

user = Blueprint('user', __name__)

@user.route("/register", methods=['GET', 'POST'])
def register():
#### ...
#### 생략
#### ...

@user.route("/login", methods=['GET', 'POST'])
def login():
#### ...
#### 생략
#### ...

#### 프로필 사진 저장을 위한 작업들을 함수로 정의하였다.
#### ...
#### 생략
#### ...

@user.route("/account", methods=['GET', 'POST'])
@login_required
def account():
#### ...
#### 생략
#### ...

@user.route("/logout")
def logout():
#### ...
#### 생략
#### ...

@user.route("/deleteAccount", methods=['GET', 'POST'])
@login_required
def deleteAccount():
    #### 로그인 상태인지 다시 한번 확인한다.
    if current_user.is_authenticated:
        form = DeleteAccountForm()
        
        #### 계정 삭제를 위한 암호 입력 페이지의 '계정 삭제 확인(confirm deletion)'버튼이 클릭된 경우
        if form.validate_on_submit():
            #### 현재 사용자 정보를 DB에서 찾아서
            user = Userdata.query.filter_by(id=current_user.id).first()
            #### 입력한 로그인 암호가 맞다면 DB에서 삭제한다.
            if bcrypt.check_password_hash(user.password, form.password.data):
                #### 예제에서는 삭제 대신 '삭제 되었음' 메시지로 대신하였다.
                print('This account is deleted: ', user.username)
                # db.session.delete(user)
                # db.session.commit()
                
                #### 계정 삭제 후 로그아웃한다.
                return redirect(url_for('user.logout'))
            else:
                return redirect(url_for('main.home'))
                
        #### 계정 정보 수정 페이지의 '계정 삭제'버튼을 클릭하면 아래 코드가 실행된다.
        #### 계정 삭제를 위한 암호 페이지에 표시될 사용자 이름과 이메일 주소를 가져온다.
        elif request.method == 'POST':
            user = {'username': current_user.username, 'useremail': current_user.email}
        else:
            return redirect(url_for('main.home'))
        
        #### 계정 삭제를 위한 암호 입력 페이지를 보여준다.
        #### 삭제될 계정에 대한 정보는 user 딕셔너리에 들어있다.
        return render_template("deleteAccount.html", title='Delete account', user=user, form=form)
    else:
        return redirect(url_for('main.home'))

 


프로젝트를 실행시키고 계정 삭제를 진행하면 아래와 같이 계정이 삭제되었다는 메시지를 볼 수 있다. 실제 계정을 삭제하는 대신 '게정이 삭제 되었음' 메시지를 표시하고 로그아웃하도록 하였다.

 

프로젝트 실행

 

계정 삭제 메시지 및 로그아웃

 

댓글