Advertisement
  1. Code
  2. Python

Membuat Aplikasi Web dari Awal dengan Python Flask dan MySQL: Bagian 7

Scroll to top
Read Time: 10 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 6
Creating a Web App From Scratch Using Python Flask and MySQL: Part 8

Indonesian (Bahasa Indonesia) translation by Aditia Dwiperdana (you can also view the original English article)

Pada bagian sebelumnya dari seri tutorial ini, kita mengimplementasi fitur unggah gambar untuk user saat menambahkan keinginan. Kita juga menambahkan beberapa pilihan yang berhubungan dengan keinginan user pada halaman Add Wish. Dalam tutorial ini kita akan selangkah lebih depan dengan mengimplementasi fitur untuk menyukai sebuah keinginan.

Memulai

Kita mulai dengan membuat klon dari tutorial bagian sebelumnya dari GitHub.

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

Setelah source code diklon, masuk ke direktori proyek dan jalankan web server.

1
cd PythonFlaskMySQLApp_Part6
2
python app.py

Arahkan browser ke http://localhost:5002/ dan aplikasi akan berjalan.

Membuat Tampilan Antarmuka Dashboard

Kita akan membuat sebuah halaman baru bernama dashboard yang akan menampilkan semua keinginan dari semua user. User mana saja bisa menyukai atau mengomentari keinginan yang mundul di dashboard. Masuk ke folder templates dan buat sebuah file bernama dashboard.html. Buka dashboard.html dan tambahkan kode HTML berikut:

1
<!DOCTYPE html>
2
<html lang="en">
3
4
<head>
5
    <title>Python Flask Bucket List App</title>
6
7
8
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
9
10
    <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
11
12
  
13
14
</head>
15
16
<body>
17
18
    <div class="container">
19
        <div class="header">
20
            <nav>
21
                <ul class="nav nav-pills pull-right">
22
                    <li role="presentation" class="active"><a href="#">Dashboard</a></li>
23
                    <li role="presentation"><a href="/userHome">My List</a></li>
24
                    <li role="presentation"><a href="/showAddWish">Add Item</a></li>
25
                    <li role="presentation"><a href="/logout">Logout</a></li>
26
                </ul>
27
            </nav>
28
            <h3 class="text-muted">Python Flask App</h3>
29
        </div>
30
31
        <div class="well">
32
            <div class="row">
33
                <div class="col-sm-4 col-md-4">
34
                    <div class="thumbnail">
35
                        <img alt="100%x200" src="static/Uploads/bucketList.png" data-holder-rendered="true" style="height: 150px; width: 150px; display: block;">
36
                        <div class="caption">
37
                            <h3>Bungee Jumping</h3>
38
                            <p>vehicula ut id elit.</p>
39
                            <p>
40
                                <button type="button" class="btn btn-danger btn-sm">
41
                                    <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span>
42
                                </button>
43
                            </p>
44
                        </div>
45
                    </div>
46
                </div>
47
                <div class="col-sm-4 col-md-4">
48
                    <div class="thumbnail">
49
                        <img alt="100%x200" src="static/Uploads/bucketList.png" data-holder-rendered="true" style="height: 150px; width: 150px; display: block;">
50
                        <div class="caption">
51
                            <h3>Bungee Jumping</h3>
52
                            <p>vehicula ut id elit.</p>
53
                            <p>
54
                                <button type="button" class="btn btn-danger btn-sm">
55
                                    <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span>
56
                                </button>
57
                            </p>
58
                        </div>
59
                    </div>
60
                </div>
61
                <div class="col-sm-4 col-md-4">
62
                    <div class="thumbnail">
63
                        <img alt="100%x200" src="static/Uploads/bucketList.png" data-holder-rendered="true" style="height: 150px; width: 150px; display: block;">
64
                        <div class="caption">
65
                            <h3>Bungee Jumping</h3>
66
                            <p>vehicula ut id elit.</p>
67
                            <p>
68
                                <button type="button" class="btn btn-danger btn-sm">
69
                                    <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span>
70
                                </button>
71
                            </p>
72
                        </div>
73
                    </div>
74
                </div>
75
76
77
                <div class="row">
78
                    <div class="col-sm-4 col-md-4">
79
                        <div class="thumbnail">
80
                            <img alt="100%x200" src="static/Uploads/bucketList.png" data-holder-rendered="true" style="height: 150px; width: 150px; display: block;">
81
                            <div class="caption">
82
                                <h3>Bungee Jumping</h3>
83
                                <p>vehicula ut id elit.</p>
84
                                <p>
85
                                    <button type="button" class="btn btn-danger btn-sm">
86
                                        <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span>
87
                                    </button>
88
                                </p>
89
                            </div>
90
                        </div>
91
                    </div>
92
                    <div class="col-sm-4 col-md-4">
93
                        <div class="thumbnail">
94
                            <img alt="100%x200" src="static/Uploads/bucketList.png" data-holder-rendered="true" style="height: 150px; width: 150px; display: block;">
95
                            <div class="caption">
96
                                <h3>Bungee Jumping</h3>
97
                                <p>vehicula ut id elit.</p>
98
                                <p>
99
                                    <button type="button" class="btn btn-danger btn-sm">
100
                                        <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span>
101
                                    </button>
102
                                </p>
103
                            </div>
104
                        </div>
105
                    </div>
106
                    <div class="col-sm-4 col-md-4">
107
                        <div class="thumbnail">
108
                            <img alt="100%x200" src="static/Uploads/bucketList.png" data-holder-rendered="true" style="height: 150px; width: 150px; display: block;">
109
                            <div class="caption">
110
                                <h3>Bungee Jumping</h3>
111
                                <p>vehicula ut id elit.</p>
112
                                <p>
113
                                    <button type="button" class="btn btn-danger btn-sm">
114
                                        <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span>
115
                                    </button>
116
                                </p>
117
                            </div>
118
                        </div>
119
                    </div>
120
                </div>
121
122
            </div>
123
124
            <footer class="footer">
125
                <p>&copy; Company 2015</p>
126
            </footer>
127
128
        </div>
129
</body>
130
131
</html>

Buka app.py dan buat rute baru bernama /showDashboard. Kita akan menggunakan rute ini untuk merender halaman dashboard.

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

Ubah fungsi /validateLogin untuk mengarahkan user dari sign-in yang sukses ke halaman dashboard, bukan ke halaman beranda user.

1
return redirect('/showDashboard')

Simpan perubahan di atas dan restart server. Arahkan browser ke http://localhost:5002 dan sign in dengan email dan password yang sah. Setelah sign in, kamu akan bisa melihat halaman dashboard.

Dashboard PageDashboard PageDashboard Page

Seperti yang terlihat pada gambar di atas, kita akan menampilkan semua butir keinginan yang dibuat berbagai usre berbeda dan memberi akses ke user lain untuk menyukai sebuah butir.

Mengisi Dashboard

Pertama, kita perlu mengambil data dari database untuk mengisi dashboard. Kita buat stored procedure untuk mendapatkan keinginan yang dibuat user.

1
USE `BucketList`;
2
DROP procedure IF EXISTS `sp_GetAllWishes`;
3
4
DELIMITER $$
5
USE `BucketList`$$
6
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_GetAllWishes`()
7
BEGIN
8
    select wish_id,wish_title,wish_description,wish_file_path from tbl_wish where wish_private = 0;
9
END$$
10
11
DELIMITER ;
12

Stored procedure di atas akan mengambil semua keinginan dari tbl_wish yang tidak ditandai keinginan pribadi.

Lalu kita buat fungsi Python untuk memanggil stored procedure sp_GetAllWishes. Buka app.py dan tambahkan kode berikut untuk fungsi getAllWishes.

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

Pada fungsi di atas, kita periksa user session yang sah lalu membuat koneksi MySQL. Menggunakan koneksi MySQL conn, kita gunakan kursor untuk memanggil stored procedure sp_GetAllWishes untuk mendapatkan data yang dibutuhkan. Setelah data didapat, kita urai hasilnya dan kembalikan dalam bentuk string JSON.

Kita panggil fungsi /getAllWishes di atas saat halaman dashboard dibuka. Buka dashboard.html, dan dengan jQuery AJAX, kita panggil /getAllWishes pada document.ready.

1
$(function() {
2
    $.ajax({
3
        url: '/getAllWishes',
4
        type: 'GET',
5
        success: function(response) {
6
            console.log(response);
7
        },
8
        error: function(error) {
9
            console.log(error);
10
        }
11
    });
12
})

Simpan perubahan di atas dan restart server. Setelah login ke aplikasi, periksa konsol browser dan kamu akan bisa lihat data yang diambil dari database.

1
[{
2
    "Description": "Bungee Jumping",
3
    "FilePath": "static/Uploads/de5f8a10-54ea-49f4-80ce-35626277047e.jpg",
4
    "Id": 10,
5
    "Title": "Bungee Jumping"
6
}, {
7
    "Description": "Mount Everest climb",
8
    "FilePath": "static/Uploads/e3e8f7fa-6cb9-4cc3-9989-a80e5089546f.png",
9
    "Id": 11,
10
    "Title": "Mount Everest climb"
11
}, {
12
    "Description": "River Rafting",
13
    "FilePath": "static/Uploads/dff3a64c-5193-42b5-9cdb-9d67a7bbacab.png",
14
    "Id": 14,
15
    "Title": "River Rafting"
16
}, {
17
    "Description": "Deep Sea Diving",
18
    "FilePath": "static/Uploads/b0656759-c038-46b4-9529-c208aaa6bfb7.png",
19
    "Id": 15,
20
    "Title": "Deep Sea Diving"
21
}]

Dengan data dari respon tersebut, kita akan isi halaman dashboard kita. Pertama, hapus kode HTML antara div .well dari dahsboard.html.

1
<div class="well">
2
3
<!-- We'll populate this dynamically -->
4
5
</div>

Pada kondisi sukses pemanggilan AJAX tersebut, urai response menjadi objek JavaScript.

1
var data = JSON.parse(response);

Kita perlu membuat HTML thumnail secara dinamis menggunakan jQuery untuk mengatur tiga keinginan sekaligus. Pertama kita buat fungsi JavaScript untuk membuat kode HTML tersebut secara dinamis. Berikut adalah kode HTML yang akan kita buat secara dinamis menggunakan jQuery:

1
<div class="col-sm-4 col-md-4">
2
    <div class="thumbnail"><img src="static/Uploads/de5f8a10-54ea-49f4-80ce-35626277047e.jpg" data-holder-rendered="true" style="height: 150px; width: 150px; display: block">
3
        <div class="caption">
4
            <h3>Testing App</h3>
5
            <p>hello</p>
6
            <p>
7
                <button type="button" class="btn btn-danger btn-sm"><span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span></button>
8
            </p>
9
        </div>
10
    </div>
11
</div>

Kita namai kode JavaScript tersebut CreateThumb. Pada fungsi ini, kita akan buat elemen HTML dan menambahkannya ke elemen orang tua untuk mendapatkan kode HTML yang ditampilkan di atas.

1
function CreateThumb(id,title, desc, filepath) {
2
  
3
    var mainDiv = $('<div>').attr('class', 'col-sm-4 col-md-4');
4
  
5
    var thumbNail = $('<div>').attr('class', 'thumbnail');
6
                                    
7
    var img = $('<img>').attr({
8
        'src': filepath,
9
        'data-holder-rendered': true,
10
        'style': 'height: 150px; width: 150px; display: block'
11
    });
12
  
13
    var caption = $('<div>').attr('class', 'caption');
14
  
15
    var title = $('<h3>').text(title);
16
  
17
    var desc = $('<p>').text(desc);
18
19
20
    var p = $('<p>');
21
  
22
    var btn = $('<button>').attr({
23
        'id': 'btn_' + id, 
24
        'type': 'button',
25
        'class': 'btn btn-danger btn-sm'
26
    });
27
  
28
    var span = $('<span>').attr({
29
        'class': 'glyphicon glyphicon-thumbs-up',
30
        'aria-hidden': 'true'
31
    });
32
33
    p.append(btn.append(span));
34
35
36
37
    caption.append(title);
38
    caption.append(desc);
39
    caption.append(p);
40
41
    thumbNail.append(img);
42
    thumbNail.append(caption);
43
    mainDiv.append(thumbNail);
44
    return mainDiv;
45
46
47
}

Kode di atas cukup sederhana jadi tidak akan saya bahas terlalu detail.

Selanjutnya, kita akan iterasi respon JSON yang sudah diurai dan buat HTML menggunakan fungsi CreateThumb. Kita berencana untuk menampilkan tiga keinginan tiap baris. Kita perlu periksa dan buat baris baru setiap tiga keinginan. Tambahkan kode berikut pada kondisi success pemanggilan AJAX pada dashboard.html.

1
var itemsPerRow = 0;
2
var div = $('<div>').attr('class', 'row');
3
for (var i = 0; i < data.length; i++) {
4
    
5
6
    if (itemsPerRow < 3) {
7
      
8
        if (i == data.length - 1) {
9
            div.append(CreateThumb(data[i].Id,data[i].Title, data[i].Description, data[i].FilePath));
10
            $('.well').append(div);
11
        } else {
12
            div.append(CreateThumb(data[i].Id,data[i].Title, data[i].Description, data[i].FilePath));
13
            itemsPerRow++;
14
        }
15
    } else {
16
        $('.well').append(div);
17
        div = $('<div>').attr('class', 'row');
18
        div.append(CreateThumb(data[i].Id,data[i].Title, data[i].Description, data[i].FilePath));
19
        if (i == data.length - 1) {
20
            $('.well').append(div);
21
        }
22
        itemsPerRow = 1;
23
    }
24
    
25
}

Simpan perubahan dan restart server. Masuk ke aplikasi dan saat berada di halaman dashboard, kamu akan bisa melihat keinginan yang dibuat oleh berbagai user, dengan pilihan untuk menyukainya.

Sekarang kita tambahkan event click pada tombol like di bawah thumbnail butir keinginan. Karena kita membuat tombol secara dinamis, kita perlu menempelkan event klik pada tombol menggunakan fungsi jQuery on.

1
$(document).on('click', '[id^="btn_"]', function() {
2
    // Event function can be added here

3
});

Mengimplementasi Fitur Like

Kita mulai dengan membuat tabel yang akan menyimpan informasi like yang sudah didapat sebuah butir keinginan. Buat tabel bernama tbl_likes.

1
CREATE TABLE `BucketList`.`tbl_likes` (
2
  `wish_id` INT NOT NULL,
3
  `like_id` INT NOT NULL AUTO_INCREMENT,
4
  `user_id` INT NULL,
5
  `wish_like` INT NULL DEFAULT 0 ;
6
  PRIMARY KEY (`like_id`));

Sekarang kapanpun user menyukai atau tidak menyukai sebuah keinginan, kita akan memperbarui tabel ini. Kita buat stored procedure MySQL untuk memperbarui tabel di atas.

1
DELIMITER $$
2
3
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_AddUpdateLikes`(
4
    p_wish_id int,
5
	p_user_id int,
6
	p_like int
7
)
8
BEGIN
9
	if (select exists (select 1 from tbl_likes where wish_id = p_wish_id and user_id = p_user_id)) then
10
11
		update tbl_likes set wish_like = p_like where wish_id = p_wish_id and user_id = p_user_id;
12
		
13
	else
14
		
15
		insert into tbl_likes(
16
			wish_id,
17
			user_id,
18
			wish_like
19
		)
20
		values(
21
			p_wish_id,
22
			p_user_id,
23
			p_like
24
		);
25
26
	end if;
27
END

Pada stored procedure ini, kita hanya memeriksa apakah seseorang sudah menyukai butir keinginan tersebut atau tidak. Jika user yang bersangkutan sudah menyukai suatu butir, kita perlu memperbarui entri like atau membuat entri baru.

Kita buat fungsi Python untuk memanggil stored procedure di atas.

1
@app.route('/addUpdateLike',methods=['POST'])
2
def addUpdateLike():
3
    try:
4
        if session.get('user'):
5
            _wishId = request.form['wish']
6
            _like = request.form['like']
7
            _user = session.get('user')
8
           
9
10
            conn = mysql.connect()
11
            cursor = conn.cursor()
12
            cursor.callproc('sp_AddUpdateLikes',(_wishId,_user,_like))
13
            data = cursor.fetchall()
14
15
            if len(data) is 0:
16
                conn.commit()
17
                return json.dumps({'status':'OK'})
18
            else:
19
                return render_template('error.html',error = 'An error occurred!')
20
21
        else:
22
            return render_template('error.html',error = 'Unauthorized Access')
23
    except Exception as e:
24
        return render_template('error.html',error = str(e))
25
    finally:
26
        cursor.close()
27
        conn.close()

Ini adalah fungsi Python yang akan memanggil stored procedure sp_AddUpdateLikes. Dalam fungsi ini kita memeriksa user session yang sah dan melempar ID keinginan dan status like untuk diperbarui oleh stored procedure. Saat user menekan tombol like, kita perlu memanggil fungsi Python /addUpdateLike. Tambahkan kode berikut pada event klik tombol like pada dashboard.html.

1
$(document).on('click', '[id^="btn_"]', function() {
2
    $.ajax({
3
        url: '/addUpdateLike',
4
        method: 'POST',
5
        data: {
6
            wish: $(this).attr('id').split('_')[1],
7
            like: 1
8
        },
9
        success: function(response) {
10
            console.log(response);
11
        },
12
        error: function(error) {
13
            console.log(error);
14
        }
15
    });
16
});

Sementara ini, kita membuat hard-code nilai like pada panggilan fungsi di atas. Simpan perubahan dan restart server. Masuk ke aplikasi dan klik tombol like di bawah thumbnail keinginan yang mana saja. Sekarang periksa tbl_likes dan kamu akan menemukan sebuah entri di tabel tersebut.

Kesimpulan

Pada tutorial kali ini, kita mengisi halaman dashboard aplikasi kita dengan berbagai keinginan dari user-user yang berbeda. Kita juga membuat tombol like pada setiap butir keinginan agar user bisa menyukai sebuah butir keinginan. Pada bagian berikutnya, kita akan lihat bagaimana untuk membuat tombol like menjadi toggle dan menampilkan jumlah like yang diterima sebuah butir keinginan.

Tulis masukan atau koreksi pada kotak komentar di bawah. Source code untuk tutorial ini tersedia di GitHub.

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.