Advertisement
  1. Code
  2. Python

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

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 5
Creating a Web App From Scratch Using Python Flask and MySQL: Part 7

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

Pada bagian sebelumnya dari seri tutorial ini, kita mengimplementasi pembagian halaman untuk daftar keinginan pada halaman beranda user. Pada tutorial kali ini, kita akan mengimplementasi opsi untuk user mengunggah gambar yang mewakili sebuah keinginan, sebuah opsi untuk menandai keinginan tercapai, dan opsi untuk mengatur privasi.

Memulai

Kita mulai dengan mengklon tutorial bagian sebelumnya dari GitHub.

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

Begitu source code di klon, masuk ke direktori proyek dan jalankan web server.

1
cd PythonFlaskMySQLApp_Part5
2
python app.py

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

Mengubah Tampilan Antarmuka

Kita mulai dengan mengubah halaman 'tambahkan keinginan' dengan menambahkan opsi untuk menunggah sebuah gambar. Masuk ke templates/addWish.html. Form pada addWish.html terlihat kecil, mari kita ubah kode HTML bootstrap agar membuat form vertikal.

Pertama kita ubah form-horizontal menjadi form vertikal, jadi hilangkan kelas form-horizontal dari form. Kita tambahkan juga tiga kontrol baru: kontrol unggah file untuk mengunggah foto, ceklis untuk menandai keinginan menjadi pribadi, dan ceklis lain untuk menandai keinginan sudah tercapai. Berikut adalah addWish.html yang sudah diubah.

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
    <script src="../static/js/jquery-1.11.2.js"></script>
13
    <style>
14
        .btn-file {
15
            position: relative;
16
            overflow: hidden;
17
        }
18
        
19
        .btn-file input[type=file] {
20
            position: absolute;
21
            top: 0;
22
            right: 0;
23
            min-width: 100%;
24
            min-height: 100%;
25
            font-size: 100px;
26
            text-align: right;
27
            filter: alpha(opacity=0);
28
            opacity: 0;
29
            outline: none;
30
            background: white;
31
            cursor: inherit;
32
            display: block;
33
        }
34
    </style>
35
36
</head>
37
38
<body>
39
40
    <div class="container">
41
        <div class="header">
42
            <nav>
43
                <ul class="nav nav-pills pull-right">
44
                    <li role="presentation" class="active"><a href="#">Add Item</a>
45
                    </li>
46
                    <li role="presentation"><a href="/logout">Logout</a>
47
                    </li>
48
                </ul>
49
            </nav>
50
            <h3 class="text-muted">Python Flask App</h3>
51
        </div>
52
53
        <form role="form" method="post" action="/addWish">
54
55
56
            <!-- Form Name -->
57
            <legend>Create Your Wish</legend>
58
59
            <!-- Text input-->
60
            <div class="form-group">
61
                <label for="txtTitle">Title</label>
62
63
                <input id="txtTitle" name="inputTitle" type="text" placeholder="placeholder" class="form-control input-md">
64
65
            </div>
66
67
            <!-- Textarea -->
68
            <div class="form-group">
69
                <label for="txtPost">Description</label>
70
71
                <textarea class="form-control" id="txtPost" name="inputDescription"></textarea>
72
73
            </div>
74
75
76
            <div class="form-group">
77
                <label for="txtPost">Photos</label>
78
79
                <div class="input-group">
80
                    <span class="input-group-btn">
81
                    <span class="btn btn-primary btn-file">
82
                        Browse&hellip; <input type="file" id="fileupload" name="file" multiple>
83
                    </span>
84
                    </span>
85
                    <input type="text" class="form-control" readonly>
86
                </div>
87
88
            </div>
89
90
            <div class="form-group">
91
                <label>Mark this as private and not visible to others.</label>
92
                <br/>
93
                <input type="checkbox"> Mark as Private <span class="glyphicon glyphicon-lock" aria-hidden="true"></span>
94
            </div>
95
96
            <div class="form-group">
97
                <label>Have you already accomplished this?</label>
98
                <br/>
99
                <input type="checkbox"> Mark as Done <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
100
            </div>
101
102
103
104
105
            <!-- Button -->
106
            <div class="form-group">
107
108
                <p class="text-center">
109
                    <input id="singlebutton" name="singlebutton" class="btn btn-primary" type="submit" value="Publish" />
110
                </p>
111
            </div>
112
113
114
        </form>
115
116
        <footer class="footer">
117
            <p>&copy; Company 2015</p>
118
        </footer>
119
120
    </div>
121
</body>
122
123
</html>

Simpan perubahan di atas dan restart server. Setelah sukses sign in, klik tautan Add Wish dan kamu bisa melihat halaman menambah keinginan yang sudah diubah.

Add Wish Page with Image UploadAdd Wish Page with Image UploadAdd Wish Page with Image Upload

Mengimplementasi Fungsi Mengunggah

Kita akan menggunakan blueimp jQuery-File-Upload untuk mengimplementasi fitur unggah file. Unduh file yang dibutuhkan dari GitHub. Ekstrak kode sumber dan tambahkan referensi skrip berikut ke addWish.html.

1
<script src="../static/js/jquery-1.11.2.js"></script>
2
3
<script src="../static/js/jquery.ui.widget.js"></script>
4
5
<script type="text/javascript" src="../static/js/jquery.fileupload.js"></script>
6
7
<script type="text/javascript" src="../static/js/jquery.fileupload-process.js"></script>
8
9
<script type="text/javascript" src="../static/js/jquery.fileupload-ui.js"></script>

Saat addWish.html dibuka, tambahkan kode inisialisasi plugin ke klik tombol unggah.

1
$(function() {
2
    $('#fileupload').fileupload({
3
        url: 'upload',
4
        dataType: 'json',
5
        add: function(e, data) {
6
            data.submit();
7
        },
8
        success: function(response, status) {
9
            console.log(response);
10
        },
11
        error: function(error) {
12
            console.log(error);
13
        }
14
    });
15
})

Seperti terlihat pada kode di atas, kita menambahkan plugin unggah file ke tombol #fileupload. Plugin unggah file mengirim file ke request handler /upload, yang akan kita definisikan dalam kode Python. Kita juga mendefinisikan sebuah fungsi add untuk mengirim data, dan kondisi success dan failure untuk menangani proses unggah yang berhasil dan gagal.

Lalu kita definisikan file upload handler Python upload dalam app.py. Definisikan sebuah rute /upload sebagai berikut:

1
@app.route('/upload', methods=['GET', 'POST'])
2
def upload():
3
    # file upload handler code will be here

Periksa apakah request adalah POST, jika iya, baca file dari request tersebut.

1
if request.method == 'POST':
2
        file = request.files['file']

Kita juga perlu untuk mendapatkan ekstensi file gambar untuk menyimpan file tersebut. Import os dan bagi nama ekstensi dari nama file.

1
extension = os.path.splitext(file.filename)[1]

Setelah kita mendapat ekstensi file, kita buat nama file unik menggunakan uuid. Import uuid dan buat nama file.

1
f_name = str(uuid.uuid4()) + extension

Buat sebuah folder bernama Uploads pada folder static. Ini adalah tempat kita menyimpan gambar yang sudah diunggah. Tambahkan jalur ke folder Upload dalam pengaturan aplikasi.

1
app.config['UPLOAD_FOLDER'] = 'static/Uploads'

Sekarang simpan file yang dikirim ke lokasi UPLOAD_FOLDER dan kembalikan nama file sebagai respon.

1
file.save(os.path.join(app.config['UPLOAD_FOLDER'], f_name))
2
return json.dumps({'filename':f_name})

Simpan perubahan di atas dan restart server. Arahkan browser ke http://localhost:5002 dan sign in menggunakan email dan password yang sah. Cobalah upload gambar menggunakan tombol browse, dan ketika selesai, periksa konsol browsermu. Kamu akan lihat nama file yang diunggah.

Mari tambahkan elemen gambar untuk menampilkan gambar yang diunggah. Ganti input text read-only menjadi kode HTML berikut.

1
<div class="pull-right">
2
    <img id="imgUpload" style="width: 140px; height: 140px;" class="img-thumbnail">
3
</div>

Pada kondisi sukses unggah file, perbarui src #imgUpload menjadi gambar yang diunggah.

1
$('#imgUpload').attr('src','static/Uploads/'+response.filename);

Simpan perubahan di atas dan restart server. Masuk ke aplikasi dan coba unggah file gambar baru, dan kamu akan bisa melihat gambar yang diupload.

Add Wish Page With UploadAdd Wish Page With UploadAdd Wish Page With Upload

Kita perlu memodifikasi struktur tabel tbl_wish untuk mencakup tiga kolom tambahan. Ubah tbl_wish seperti berikut ini:

1
ALTER TABLE `BucketList`.`tbl_wish` 
2
ADD COLUMN `wish_file_path` VARCHAR(200) NULL AFTER `wish_date`,
3
ADD COLUMN `wish_accomplished` INT NULL DEFAULT 0 AFTER `wish_file_path`,
4
ADD COLUMN `wish_private` INT NULL DEFAULT 0 AFTER `wish_accomplished`;

Lalu ubah stored procedure sp_addWish dan sp_updateWish untuk mencakup kolom baru ke database.

Ubah stored procedure sp_addWish agar mencakup tiga kolom baru.

1
USE `BucketList`;
2
DROP procedure IF EXISTS `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
	IN p_file_path varchar(200),
11
	IN p_is_private int,
12
	IN p_is_done int
13
)
14
BEGIN
15
	insert into tbl_wish(
16
		wish_title,
17
		wish_description,
18
		wish_user_id,
19
		wish_date,
20
		wish_file_path,
21
		wish_private,
22
		wish_accomplished
23
	)
24
	values
25
	(
26
		p_title,
27
		p_description,
28
		p_user_id,
29
		NOW(),
30
		p_file_path,
31
		p_is_private,
32
		p_is_done
33
	);
34
END$$
35
36
DELIMITER ;
37

Ubah pula stored procedure sp_updateWish agar mencakup tiga kolom baru.

1
USE `BucketList`;
2
DROP procedure IF EXISTS `sp_updateWish`;
3
4
DELIMITER $$
5
USE `BucketList`$$
6
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_updateWish`(
7
IN p_title varchar(45),
8
IN p_description varchar(1000),
9
IN p_wish_id bigint,
10
In p_user_id bigint,
11
IN p_file_path varchar(200),
12
IN p_is_private int,
13
IN p_is_done int
14
)
15
BEGIN
16
update tbl_wish set 
17
    wish_title = p_title,
18
	wish_description = p_description,
19
	wish_file_path = p_file_path,
20
	wish_private = p_is_private,
21
	wish_accomplished = p_is_done
22
	where wish_id = p_wish_id and wish_user_id = p_user_id;
23
END$$
24
25
DELIMITER ;
26

Lalu ubah request handler /addWish agar membaca kolom yang baru dikirim dan melemparnya ke stored procedure.

1
if request.form.get('filePath') is None:
2
    _filePath = ''
3
else:
4
    _filePath = request.form.get('filePath')
5
    
6
if request.form.get('private') is None:
7
    _private = 0
8
else:
9
    _private = 1
10
    
11
if request.form.get('done') is None:
12
    _done = 0
13
else:
14
    _done = 1

Setelah nilai dibaca, kita lempar ke pemanggilan stored procedure MySQL.

1
cursor.callproc('sp_addWish',(_title,_description,_user,_filePath,_private,_done))

Pada halaman addWish.html, kita perlu mengatur atribut name untuk elemen yang akan dikirim. Tambahkan name ke kedua ceklis yang baru ditambahkan.

1
<input name="private" type="checkbox"> Mark as Private <span class="glyphicon glyphicon-lock" aria-hidden="true"></span>
2
3
<input name="done" type="checkbox"> Mark as Done <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>

Kita juga perlu mengirim jalur file yang diunggah. Kita buat input field tersembunyi dan mengatur nilainya di kondisi sukses unggah file.

1
<input type="hidden" name="filePath" id="filePath"></input>

Atur nilainya pada kondisi sukses unggah file.

1
success: function(response, status) {
2
3
    var filePath = 'static/Uploads/' + response.filename;
4
    $('#imgUpload').attr('src', filePath);
5
6
    $('#filePath').val(filePath);
7
8
}

Simpan perubahan di atas dan restart server. Masuk menggunkan kredensial yang sah dan coba tambahkan keinginan baru dengan detail yang dibutuhkan. Setelah ditambahkan dengan sukses, butir tersebut akan mundul di daftar pada halaman beranda user.

Ubah Implementasi Edit Keinginan

Pertama kita perlu menambahkan kode HTML untuk tiga kolom baru. Buka userHome.html dan tambahkan kode HTML berikut setelah title dan description HTML.

1
<div class="form-group">
2
    <label for="txtPost">Photos</label>
3
4
    <div class="input-group">
5
        <span class="input-group-btn">
6
                    <span class="btn btn-primary btn-file">
7
                        Browse&hellip; <input type="file" id="fileupload" name="file" multiple>
8
                    </span>
9
        </span>
10
        <div class="pull-right">
11
            <img id="imgUpload" style="width: 140px; height: 140px;" class="img-thumbnail">
12
            <input type="hidden" name="filePath" id="filePath"></input>
13
        </div>
14
    </div>
15
16
</div>
17
18
<div class="form-group">
19
    <label>Mark this as private and not visible to others.</label>
20
    <br/>
21
    <input id="chkPrivate" name="private" type="checkbox"> Mark as Private <span class="glyphicon glyphicon-lock" aria-hidden="true"></span>
22
</div>
23
24
<div class="form-group">
25
    <label>Have you already accomplished this?</label>
26
    <br/>
27
    <input id="chkDone" name="done" type="checkbox"> Mark as Done <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
28
</div>

Kita perlu mengambil beberapa data yang dibutuhkan untuk mengisi kolom-kolom di atas saat proses edit. Mari ubah stored procedure sp_GetWishById untuk mencakup kolom tambahan sebagai berikut:

1
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_GetWishById`(
2
IN p_wish_id bigint,
3
In p_user_id bigint
4
)
5
BEGIN
6
select wish_id,wish_title,wish_description,wish_file_path,wish_private,wish_accomplished from tbl_wish where wish_id = p_wish_id and wish_user_id = p_user_id;
7
END

Lalu, ubah string JSON pada rute /getWishById untuk mencakup kolom baru. Ubah daftar keinginan pada /getWishById sebagai berikut:

1
wish.append({'Id':result[0][0],'Title':result[0][1],'Description':result[0][2],'FilePath':result[0][3],'Private':result[0][4],'Done':result[0][5]})

Untuk merender hasilnya, kita perlu mengurai data yang diterima di kondisi sukses fungsi JavaScript Edit di userHome.html.

1
success: function(res) {
2
3
    var data = JSON.parse(res);
4
    
5
    $('#editTitle').val(data[0]['Title']);
6
  
7
    $('#editDescription').val(data[0]['Description']);
8
  
9
    $('#imgUpload').attr('src', data[0]['FilePath']);
10
  
11
    if (data[0]['Private'] == "1") {
12
        $('#chkPrivate').attr('checked', 'checked');
13
    }
14
  
15
    if (data[0]['Done'] == "1") {
16
        $('#chkDone').attr('checked', 'checked');
17
    }
18
  
19
    $('#editModal').modal();
20
21
}

Simpan perubahan dan restart server. Masuk dengan kredensial yang sah, dan pada halaman beranda user, cobalah untuk mengedit sebuah butir keinginan dari daftar keinginan. Kamu akan mendapati data yang sudah terisi di popup Edit.

Edit Pop Up With Additional FieldsEdit Pop Up With Additional FieldsEdit Pop Up With Additional Fields

Sekarang, sama dengan yang kita lakukan pada halaman menambahkan keinginan, tambahkan referensi skrip jQuery-File-Upload di userHome.html.

1
<script src="../static/js/jquery-1.11.2.js"></script>
2
3
<script src="../static/js/jquery.ui.widget.js"></script>
4
5
<script type="text/javascript" src="../static/js/jquery.fileupload.js"></script>
6
7
<script type="text/javascript" src="../static/js/jquery.fileupload-process.js"></script>
8
9
<script type="text/javascript" src="../static/js/jquery.fileupload-ui.js"></script>

Inisialisasi kontrol unggah file pada popup edit menggunakan kode yang sama yang kita gunakan pada halaman menambahkan keinginan.

1
$(function() {
2
    $('#fileupload').fileupload({
3
        url: 'upload',
4
        dataType: 'json',
5
        add: function(e, data) {
6
            data.submit();
7
        },
8
        success: function(response, status) {
9
            
10
            var filePath = 'static/Uploads/' + response.filename;
11
            $('#imgUpload').attr('src', filePath);
12
            $('#filePath').val(filePath);
13
           
14
        },
15
        error: function(error) {
16
            console.log(error);
17
        }
18
    });
19
})

Lalu kita perlu mengubah tombol Update pada popup Edit untuk mencakup kolom tambahan. Saat menekan tombol btnUpdate, ubah data parameter yang dilempar untuk mencakup tiga kolom tambahan sebagai berikut:

1
data : {title:$('#editTitle').val(),description:$('#editDescription').val(),id:localStorage.getItem('editId'),filePath:$('#imgUpload').attr('src'),isPrivate:$('#chkPrivate').is(':checked')?1:0,isDone:$('#chkDone').is(':checked')?1:0}

Buka app.py dan ubah request handler /updateWish untuk mengurai kolom yang baru ditambahkan.

1
_filePath = request.form['filePath']
2
_isPrivate = request.form['isPrivate']
3
_isDone = request.form['isDone']

Ubah prosedur yang memanggil fungsi untuk mencakup parameter tambahan.

1
cursor.callproc('sp_updateWish',(_title,_description,_wish_id,_user,_filePath,_isPrivate,_isDone))

Buka sp_updateWish dan ubah untuk mencakup kolom yang baru ditambahkan.

1
DELIMITER $$
2
3
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_updateWish`(
4
IN p_title varchar(45),
5
IN p_description varchar(1000),
6
IN p_wish_id bigint,
7
In p_user_id bigint,
8
IN p_file_path varchar(200),
9
IN p_is_private int,
10
IN p_is_done int
11
)
12
BEGIN
13
update tbl_wish set 
14
    wish_title = p_title,
15
	wish_description = p_description,
16
	wish_file_path = p_file_path,
17
	wish_private = p_is_private,
18
	wish_accomplished = p_is_done
19
	where wish_id = p_wish_id and wish_user_id = p_user_id;
20
END

Simpan semua perubahan di atas dan restart server. Masuklah dengan kredential yang sah dan coba edit dan perbarui entri yang sudah ada.

Penutup

Pada tutorial bagian ini, kita lihat bagaimana cara mengintegrasi dan menggunakan plugin blueimp jQuery-File-Upload untuk mengunggah gambar pada aplikasi Python Flask kita. Pada bagian berikutnya, kita akan menampilkan keinginan yang sudah tercapai oleh user pada halaman utama dan menambahkan fitur untuk menyukai keinginan.

Beri tahu kami pendapat, koreksi, dan saran pada komentar di bawah. Source code tutorial ini tersedia pada 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.