Advertisement
  1. Code
  2. Python

파이썬 플라스크와 MySQL을 이용한 웹 앱 개발: 3부

Scroll to top
Read Time: 7 min
This post is part of a series called Creating a Web App From Scratch Using Python Flask and MySQL.
Creating a Web App From Scratch Using Python Flask and MySQL: Part 2
Creating a Web App From Scratch Using Python Flask and MySQL: Part 4

() translation by (you can also view the original English article)

이 연재 기사의 2부에서는 버킷 리스트 애플리케이션의 로그인 및 로그아웃 기능을 구현했습니다. 3부에서는 사용자가 버킷 리스트 항목을 추가하고 표시하는 데 필요한 백엔드와 프런트엔드를 구현하겠습니다..

시작하기

먼저 깃허브(GitHub)에서 튜토리얼의 이전 내용을 복제합니다.

1
git clone https://github.com/jay3dec/PythonFlaskMySQLApp_Part2.git

소스코드가 복제되면 프로젝트 디렉터리로 이동해서 웹 서버를 구동합니다.

1
cd PythonFlaskMySQLApp_Part2
2
python app.py

브라우저에서 http://localhost:5002/로 이동하면 실행 중인 애플리케이션을 볼 수 있을 것입니다.

Bucket List App Home PageBucket List App Home PageBucket List App Home Page

버킷 리스트 항목 추가

1단계: 항목 추가 인터페이스 만들기

로그인한 사용자가 버킷 리스트 항목을 추가하는 인터페이스를 만드는 것으로 시작하겠습니다. 프로젝트 디렉터리 내의 templates 폴더로 이동한 후 addWish.html이라는 파일을 만듭니다. addWish.html을 열고 다음 HTML 코드를 추가합니다.

1
<!DOCTYPE html>
2
<html lang="en">
3
4
<head>
5
    <title>Python Flask Bucket List App</title>
6
7
8
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
9
10
    <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
11
12
    <script src="../static/js/jquery-1.11.2.js"></script>
13
14
15
</head>
16
17
<body>
18
19
    <div class="container">
20
        <div class="header">
21
            <nav>
22
                <ul class="nav nav-pills pull-right">
23
                    <li role="presentation" class="active"><a href="#">Add Item</a>
24
                    </li>
25
                    <li role="presentation"><a href="/logout">Logout</a>
26
                    </li>
27
                </ul>
28
            </nav>
29
            <h3 class="text-muted">Python Flask App</h3>
30
        </div>
31
        <section>
32
            <form class="form-horizontal" method="post" action="/addWish">
33
                <fieldset>
34
35
                    <!-- Form Name -->
36
                    <legend>Create Your Wish</legend>
37
38
                    <!-- Text input-->
39
                    <div class="form-group">
40
                        <label class="col-md-4 control-label" for="txtTitle">Title</label>
41
                        <div class="col-md-4">
42
                            <input id="txtTitle" name="inputTitle" type="text" placeholder="placeholder" class="form-control input-md">
43
                        </div>
44
                    </div>
45
46
                    <!-- Textarea -->
47
                    <div class="form-group">
48
                        <label class="col-md-4 control-label" for="txtPost">Post</label>
49
                        <div class="col-md-4">
50
                            <textarea class="form-control" id="txtPost" name="inputDescription"></textarea>
51
                        </div>
52
                    </div>
53
54
                    <!-- Button -->
55
                    <div class="form-group">
56
                        <label class="col-md-4 control-label" for="singlebutton"></label>
57
                        <div class="col-md-4">
58
                            <input id="singlebutton" name="singlebutton" class="btn btn-primary" type="submit" value="Publish" />
59
                        </div>
60
                    </div>
61
62
                </fieldset>
63
            </form>
64
65
        </section>
66
        <footer class="footer">
67
            <p>&copy; Company 2015</p>
68
        </footer>
69
70
    </div>
71
</body>
72
73
</html>

app.py를 열고 Add Wish 페이지를 표시하는 새로운 라우트와 메서드를 추가합니다.

1
@app.route('/showAddWish')
2
def showAddWish():
3
    return render_template('addWish.html')

userHome.html을 열고 Add Wish 페이지로 연결되는 새 메뉴 항목을 추가합니다.

1
<li role="presentation"><a href="/showAddWish">Add Wish</a></li>

변경 사항을 저장하고 서버를 다시 시작합니다. 브라우저에서 http://localhost:5002로 이동한 후 유효한 이메일 주소와 비밀번호를 사용해 로그인합니다. 로그인한 후 Add Wish 링크를 클릭하면 Add Wish 페이지가 표시됩니다.

Add Bucket List ItemAdd Bucket List ItemAdd Bucket List Item

2단계: 데이터베이스 구현

버킷 리스트에 항목을 추가하려면 tbl_wish라는 테이블을 만들 필요가 있습니다.

1
CREATE TABLE `tbl_wish` (
2
  `wish_id` int(11) NOT NULL AUTO_INCREMENT,
3
  `wish_title` varchar(45) DEFAULT NULL,
4
  `wish_description` varchar(5000) DEFAULT NULL,
5
  `wish_user_id` int(11) DEFAULT NULL,
6
  `wish_date` datetime DEFAULT NULL,
7
  PRIMARY KEY (`wish_id`)
8
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

tbl_wish 테이블에는 title, description, 그리고 희망사항을 작성한 사용자의 ID를 담을 것입니다.

다음으로 tbl_wish 테이블에 항목을 추가하는 MySQL 저장 프로시저를 생성해야 합니다.

1
USE `BucketList`;
2
DROP procedure IF EXISTS `BucketList`.`sp_addWish`;
3
4
DELIMITER $$
5
USE `BucketList`$$
6
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_addWish`(
7
    IN p_title varchar(45),
8
  IN p_description varchar(1000),
9
	IN p_user_id bigint
10
)
11
BEGIN
12
	insert into tbl_wish(
13
		wish_title,
14
		wish_description,
15
		wish_user_id,
16
		wish_date
17
	)
18
	values
19
	(
20
		p_title,
21
		p_description,
22
		p_user_id,
23
		NOW()
24
	);
25
END$$
26
27
DELIMITER ;
28
;

3단계: MySQL 저장 프로시저를 호출하는 파이썬 메서드 작성

app.pyaddWish라는 메서드를 만듭니다.

1
@app.route('/addWish',methods=['POST'])
2
def addWish():
3
    # Code will be here 

이 메서드로 데이터를 전송할 것이므로 정의한 라우트에 명시적으로 선언했습니다.

addWish 메서드가 호출될 때 세션 변수인 user가 존재하는지 확인해서 실제 호출인지 확인해야 합니다. 세션을 확인하고 나면 전송된 titledescription을 읽습니다.

1
_title = request.form['inputTitle']
2
_description = request.form['inputDescription']
3
_user = session.get('user')

필요한 입력값을 얻으면 MySQL 연결을 열고 sp_addWish 저장 프로시저를 호출합니다.

1
conn = mysql.connect()
2
cursor = conn.cursor()
3
cursor.callproc('sp_addWish',(_title,_description,_user))
4
data = cursor.fetchall()

저장 프로시저를 실행한 후에는 데이터베이스에 변경 사항을 커밋해야 합니다.

1
if len(data) is 0:
2
    conn.commit()
3
    return redirect('/userHome')
4
else:
5
    return render_template('error.html',error = 'An error occurred!')

다음은 addWish 메서드의 전체 코드입니다.

1
@app.route('/addWish',methods=['POST'])
2
def addWish():
3
    try:
4
        if session.get('user'):
5
            _title = request.form['inputTitle']
6
            _description = request.form['inputDescription']
7
            _user = session.get('user')
8
9
            conn = mysql.connect()
10
            cursor = conn.cursor()
11
            cursor.callproc('sp_addWish',(_title,_description,_user))
12
            data = cursor.fetchall()
13
14
            if len(data) is 0:
15
                conn.commit()
16
                return redirect('/userHome')
17
            else:
18
                return render_template('error.html',error = 'An error occurred!')
19
20
        else:
21
            return render_template('error.html',error = 'Unauthorized Access')
22
    except Exception as e:
23
        return render_template('error.html',error = str(e))
24
    finally:
25
        cursor.close()
26
        conn.close()

모든 소스코드를 저장하고 서버를 다시 시작합니다. 브라우저에서 http://localhost:5002로 이동한 후 유효한 이메일 주소와 비밀번호를 사용해 로그인합니다. 로그인한 후 Add Wish 링크를 클릭합니다. 희망사항의 titledescription을 입력하고 Publish를 클릭합니다. 희망사항이 성공적으로 추가되면 사용자 홈 페이지로 리디렉션될 것입니다. MySQL 데이터베이스에 로그인해서 보면 tbl_wish 테이블에 희망사항이 들어있을 것입니다.

버킷 리스트 항목 보여주기

1단계: 희망사항을 조회하는 저장 프로시저 작성

사용자가 만든 희망사항을 가져오는 MySQL 저장 프로시저를 만들어 봅시다. 이 프로시저에서는 사용자 ID를 매개변수로 받아 특정 사용자 ID가 만든 희망사항 데이터 집합을 반환합니다.

1
USE `BucketList`;
2
DROP procedure IF EXISTS `sp_GetWishByUser`;
3
4
DELIMITER $$
5
USE `BucketList`$$
6
CREATE PROCEDURE `sp_GetWishByUser` (
7
IN p_user_id bigint
8
)
9
BEGIN
10
    select * from tbl_wish where wish_user_id = p_user_id;
11
END$$
12
13
DELIMITER ;
14

2단계: 데이터를 조회하기 위한 파이썬 메서드 작성

다음으로, 사용자가 만든 희망사항을 가져오는 sp_GetWishByUser 저장 프로시저를 호출하는 파이썬 메서드를 작성해 봅시다. app.pygetWish라는 메서드를 추가합니다.

1
@app.route('/getWish')
2
def getWish():
3
    try:
4
        if session.get('user'):
5
            _user = session.get('user')
6
        else:
7
            return render_template('error.html', error = 'Unauthorized Access')
8
    except Exception as e:
9
        return render_template('error.html', error = str(e))

위의 코드에서 볼 수 있듯이 이 메서드는 유효한 user 세션에서만 호출될 수 있습니다. 유효한 사용자 세션을 검사하고 나면 MySQL 데이터베이스에 대한 연결을 생성하고 sp_GetWishByUser 저장 프로시저를 호출합니다.

1
 _user = session.get('user')
2
3
# Connect to MySQL and fetch data

4
con = mysql.connect()
5
cursor = con.cursor()
6
cursor.callproc('sp_GetWishByUser',(_user,))
7
wishes = cursor.fetchall()

MySQL에서 데이터를 가져오면 JSON으로 반환하기 쉽게 데이터를 파싱해서 dictionary로 변환합니다.

1
wishes_dict = []
2
for wish in wishes:
3
    wish_dict = {
4
        'Id': wish[0],
5
        'Title': wish[1],
6
        'Description': wish[2],
7
        'Date': wish[4]}
8
wishes_dict.append(wish_dict)

데이터를 dictionary로 변환하고 나면 해당 데이터를 JSON으로 변환한 후 반환합니다.

1
return json.dumps(wishes_dict)

다음은 getWish 메서드의 전체 코드입니다.

1
@app.route('/getWish')
2
def getWish():
3
    try:
4
        if session.get('user'):
5
            _user = session.get('user')
6
7
            con = mysql.connect()
8
            cursor = con.cursor()
9
            cursor.callproc('sp_GetWishByUser',(_user,))
10
            wishes = cursor.fetchall()
11
12
            wishes_dict = []
13
            for wish in wishes:
14
                wish_dict = {
15
                        'Id': wish[0],
16
                        'Title': wish[1],
17
                        'Description': wish[2],
18
                        'Date': wish[4]}
19
                wishes_dict.append(wish_dict)
20
21
            return json.dumps(wishes_dict)
22
        else:
23
            return render_template('error.html', error = 'Unauthorized Access')
24
    except Exception as e:
25
        return render_template('error.html', error = str(e))

3단계: JSON 데이터를 HTML에 바인딩

사용자 홈 페이지가 로드되면 jQuery AJAX를 이용해 getWish 메서드를 호출하고 조회된 데이터를 HTML에 바인딩합니다. userHome.html에서 다음과 같은 jQuery AJAX 스크립트를 추가합니다.

1
<script>
2
    $(function() {
3
        $.ajax({
4
            url: '/getWish',
5
            type: 'GET',
6
            success: function(res) {
7
                console.log(res);
8
            },
9
            error: function(error) {
10
                console.log(error);
11
            }
12
        });
13
    });
14
</script>

변경 사항을 저장하고 서버를 다시 시작합니다. 유효한 이메일 주소와 비밀번호로 로그인하고 나면 브라우저 콘솔을 통해 다음과 같이 데이터베이스에서 희망사항 목록을 가져왔는지 확인합니다.

1
[{
2
    "Date": "Fri, 23 Jan 2015 23:26:05 GMT",
3
    "Description": "I want to climb Mount Everest",
4
    "Id": 1,
5
    "Title": "Climb Everest"
6
}, {
7
    "Date": "Fri, 23 Jan 2015 23:27:05 GMT",
8
    "Description": "I want to jump from top of a mountain",
9
    "Id": 2,
10
    "Title": "Bungee Jump"
11
}]

이제 JSON 데이터를 순회해 데이터를 HTML에 바인딩해야 합니다. 여기서는 부트스트랩의 list-group을 이용해 희망사항 목록의 항목을 표시하겠습니다. 다음은 list-group의 기본 템플릿입니다.

1
<div class="list-group">
2
  <a href="#" class="list-group-item active">
3
    <h4 class="list-group-item-heading">Wish Title</h4>
4
    <p class="list-group-item-text">Wish Description</p>
5
  </a>
6
</div>

userHome.htmljumbotron div에 위의 HTML 코드를 추가합니다. 브라우저에 표시되는 모습은 다음과 같습니다.

list-group in User Homelist-group in User Homelist-group in User Home

이제 각 희망사항 목록마다 위의 list-group div를 동적으로 생성해 jumbotron div에 덧붙이기만 하면 됩니다. getWish 함수 호출의 성공 콜백에서 다음과 같은 div를 작성합니다.

1
var div = $('<div>')
2
    .attr('class', 'list-group')
3
    .append($('<a>')
4
        .attr('class', 'list-group-item active')
5
        .append($('<h4>')
6
            .attr('class', 'list-group-item-heading'),
7
            $('<p>')
8
            .attr('class', 'list-group-item-text')));

여기서는 위의 div를 복사해서 각 희망사항 항목에 대한 list-group div를 만들겠습니다. 그런 다음 반환된 JSON 문자열을 자바스크립트 객체로 파싱합니다.

1
var wishObj = JSON.parse(res);

이제 wishObj를 순회해 각 희망사항 항목에 대해 새 div를 복제해서 jumbotron div에 덧붙입니다.

1
var wish = '';
2
3
$.each(wishObj, function(index, value) {
4
    wish = $(div).clone();
5
    $(wish).find('h4').text(value.Title);
6
    $(wish).find('p').text(value.Description);
7
    $('.jumbotron').append(wish);
8
});

위의 변경 사항을 저장하고 서버를 다시 시작합니다. 유효한 이메일 주소와 비밀번호를 사용해 로그인하면 특정 사용자가 만든 희망사항 목록을 볼 수 있을 것입니다.

User Home Page Populated with WishesUser Home Page Populated with WishesUser Home Page Populated with Wishes

정리

이번 튜토리얼에서는 로그인한 사용자가 희망사항을 작성하기위한 인터페이스를 구현했습니다. 또한 사용자 홈 페이지에서 만들어진 희망사항을 가져와 표시하는 데 필요한 메서드와 데이터베이스 저장 프로시저도 구현했습니다.

이번 연재 기사의 4부에서는 사용자 홈 페이지에 표시된 희망사항 목록에 대한 EditDelete 기능을 구현하는 방법을 살펴보겠습니다.

이 튜토리얼의 소스코드는 깃허브에서 확인하실 수 있습니다.

아래 댓글로 여러분의 생각을 알려주세요!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.