- Pembicara : Yunindyo Prabowo (@ypraw)
- Waktu :
- Materi : Ngoding Web dengan Flask
Text Editor : vscode, atom,sublime, notepads ++, vim, pycharm, pilih salah satu atau ada pilihan lain, terserah kalian yang penting nyaman.
Environment : Python 3.6, mysql db( xampp,lampp, etc)
NOTED : Cara ini disarankan oleh banyak expert python, jika tidak ingin menggunakan virtual environtment, silahkan menuju step berikutnya.
Pada python, ada suatu isolated system yg dinamakan virtual environtment, tujuannya adalah mengisolasi program-program yg kita buat, perumpamaan di program a kita membutuhkan library x.1 sedangkan di program b kita membutuhkan library x.2, jika kita menginstall keduanya pada global environtment tentu akan terjadi bentrokan terhadap library2 tersebut.
- Internet connection required*
buka cmd, ketikkan :
python -m venv myenv D:\namaFolder
kemudian arahkan cmd ke directory tempat menginstall virtual environtment, dalam hal ini D:\namafolder lalu aktivasi virtual environtmentnya :
Scripts\activate.bat
Untuk mendeaktivasi, ketikkan :
deactivate
Sebelum menginstall flask, sekali lagi pastikan bahwa virtual environtment telah aktif (jika menggunakan virtual environment, jika tidak, abaikan).
kita akan melakukan instalasi via pip, semacam package manager di python, ketikkan script berikut di cmd:
pip install flask
untuk mengecek library yg kita install, ketikkan :
pip list
Dengan flask, kita akan membuat crud sederhana menggunakan mysql, tentunya dibutuhkan connector agar python dan mysql dapat berkomunikasi, dalam hal ini kita menggunakan mysqlclient, instalasinya masih sama menggunakan pip :
pip install mysqlclient
PERHATIAN !!! jika mengalami error saat instalasi, gunakan beberapa opsi dibawah ini Install visual c++ (biasanya terjadi jika belum menginstall visual c++2010 atau ikuti requirement pada pesan erornya) Install menggunakan file whl yang dapat di download disini downgrade versi mysqlclient dengan (RECOMMENDED) 1. pip install mysqlclient==1.3.9
2. pip install mysqlclient==1.3.4
Bagi yang menggunakan virtual environtment pastikan bahwa virtual environtment kalian telah aktif
Buatlah direktori project seperti dibawah ini, untuk penemaan WebFlask bisa dises uaikan dengan selera, diikuti folder templates dan static (_untuk file tiap-tiap folder dibuat mengikuti jalannya kulgram, untuk file css, js, fontawesome bisa diletakkan sekarang sesuai susunan folder disini saya menggunakan bootstrap 3.3.7 _)
- WebFlask
- templates
- index.html
- hello.html
- base.html
- inputPage.html
- updatePage.html
- static
- css
- bootstrap.min.css
- js
- fonts
- font-awesome.min.css
- pictures
- css
- hello.py
- templates
buka terminal arahkan pada folder direktori project kalian, dalam contoh saya yaitu webFlask
Buatlah file hello.py dan isikan kodingan berikut ini :
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World'
kemudian save. Setelah itu kita akan menge-set flask pada environtment windows, ketikkan
set FLASK_APP=hello.py
dilanjutkan dengan running flasknya,
flask run
buka browser kalian, arahkan ke urlnya, dan voila
Mari kita kelangkah selanjutnya yaitu templating, seperti framework pada umumnya, flask juga memiliki fitur templating, disini kita bisa menurunkan suatu template untuk digunakan template-template lain. Sebelum itu, kita akan mencoba untuk merender template pertama kita.
Pada folder templates, kita coba buat file HTML, dicontoh ini saya menggunakan nama hello.html
ketikan tag HTML berikut,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HELLO</title>
</head>
<body>
<<h1>hello {{nama}}</h1>
</body>
</html>
kemudian pada file hello.py kita perbaiki koding sebelumnya menjadi begini,
from flask import Flask, render_template
app = Flask(__name__, static_url_path='')
@app.route('/')
def index(nama='yunindyo'):
return render_template('hello.html', nama=nama)
lalu running flasknya, dan lihat resultnya.
Seperti yang saya bilang sebelumnya, flask juga mendukung modularitas template, yaitu proses memecah file html menjadi bagian-bagian kecil agar reusable, atau dengan kata lain bisa digunakan kembali oleh file hmtl lainnya. Cara ini juga memberikan keuntungan lain yaitu bisa membuat koding lebih ringkas dari yang seharusnya. Pada flask, templating dibantu oleh engine jinja2.
Panduan umumnya, template utama dinamakan base.html tapi kalo mau diganti nama lain ya monggo...
Selanjutnya, kita buat file base.html pada folder templates, jangan lupa taruh file bootstrap dan font awesome di folder static dengan susunan seperti yang diawal saya sebutkan sebagai bumbu untuk mempercantik web kita. ketikkan tag html berikut,
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Windows 10 Community ID{% endblock %}</title>
<link rel="shortcut icon" href="/pictures/iconp.png">
<!-- Bootstrap -->
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/css/style.css">
<link rel="stylesheet" href="/assets/css/bootstrap.min.css">
{% endblock %}
</head>
<body>
{% block navMenu %}
<div class="container">
<div class="page-header">
<h1><img src="/pictures/logo.png" > <small>Ngoding web dengan FLask</small></h1>
</div>
<nav class="navbar navbar-inverse">
<div class="container">
<ul class="nav navbar-nav">
<li class="active"><a href="{{url_for('index')}}">Home</a></li>
<li><a href="{{url_for('inputPages')}}">Input</a></li>
</ul>
</div>
</nav>
</div>
{% endblock %}
<div class="container">
{% block content %}
{% endblock %}
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/assets/js/jquery-min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/assets/js/bootstrap.min.js"></script>
<script type="text/javascript">
{% block js %}
{% endblock %}
</script>
</body>
</html>
Karena tujuan tutorial ini diadakan adalah mengenalkan framework bahasa pemrograman web selain php, yang dimana pada umumnya saat pengaplikasiannya nanti membutuhkan database, maka kulgram kali ini saya juga sedikit mendemonstrasikan koneksi database dengan aplikasi flask kita.
Sebelum memulainya pastikan mysql servernya sudah aktif, dalam demonstrasi kali ini saya menggunaan phpmyadmin. Dan juga jangan lupa menginstall mysqlclient sebagai connector pythonnya.
oke pada menu phpmyadmin, buka mode console, dan ketikkan syntax sql berikut,
CREATE TABLE `pos`.`products` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NOT NULL,
`price` INT NOT NULL,
`stock` INT NOT NULL,
PRIMARY KEY (`id`));
Untuk pertama kali kita akan membuat fitur input pada aplikasi web kita, pertama kita buat file views.py di folder webFlask, berikut kodenya,
from flask import Flask, render_template, request, redirect
import MySQLdb as con
app = Flask(__name__, static_url_path='')
def GetConnection(): # method connections
connection = con.connect('127.0.0.1', 'root', '', 'pos')
cursor = connection.cursor()
return cursor, connection
# get cursor for connection
cur = GetConnection()
@app.route('/')
def index():
cur[0].execute("SELECT * FROM product")
# result values
result=cur[0].fetchall()
return render_template("index.html",result=result)
@app.route('/input-pages', methods=['GET', 'POST'])
def inputPages():
if request.method == "GET":
return render_template("inputPage.html")
# ambil data dari form add product
name = request.form["name"]
price = request.form["price"]
stock = request.form["stock"]
# input ke database
cur[0].execute("INSERT INTO product values ((%s),(%s),(%s),(%s))",
(None, name, price, stock,))
cur[1].commit()
return redirect('/')
lalu kita buat file hmtlnya, ada dua bagian yang akan kita buat, pertama file index dan yang kedua adalah file input data. Pada demonstrasi ini saya menggunakan index.html, berikut ini tag htmlnya,
index.html
{% extends 'base.html' %}
{% block title %} Index {% endblock %}
{% block content %}
{% if resultProduct %}
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="panel-title">
<center><h1>Daftar Barang</h1></center>
</div>
</div>
<div class="panel-body">
<div class="table-responsive">
<table class="table table-hover ">
<thead>
<th>No</th>
<th>ID Barang</th>
<th>Nama Barang</th>
<th>Harga Barang</th>
<th>Stok Barang</th>
<th>Action</th>
</thead>
<tbody>
{% for item in resultProduct %}
<tr>
<td>{{ loop.index }}</td>
<td>{{item[0]}}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
<td>{{ item[3] }}</td>
<td>
<a href="#" class="glyphicon glyphicon-pencil" aria-hidden="true">edit</a>
<a href="#" class="glyphicon glyphicon-trash
">delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<center></center>
</div>
</div>
</div>
</div>
<div class="col-md-3">
</div>
</div>
{% endif %}
{% endblock %}
inputPage.html
{% extends "base.html" %}
{% block title %} Input Page {% endblock %}
{% block content %}
<div class="col-md-4">
</div>
<div class="col-md-4">
<div class="panel panel-info">
<div class="panel-heading">
<center><h3><strong>Tambah Produk</strong></h3></center>
</div>
<div class="panel-body">
<form action="" method="post">
<div class="form-group">
<label for="name">Name</label>
<input name="name" type="text" class="form-control" id="name" placeholder="Name">
</div>
<div class="form-group">
<label for="price">Price</label>
<input name="price" type="text" class="form-control" id="price" placeholder="Price">
</div>
<div class="form-group">
<label for="stock">Stock</label>
<input name="stock" type="text" class="form-control" id="stock" placeholder="Stock">
</div>
<center><button type="submit" class="btn btn-info">Submit</button></center>
</form>
</div>
</div>
</div>
<div class="col-md-4">
</div>
{% endblock %}
tambahkan method productUpdates pada views, sehingga views.py yang sekarang menjadi,
views.py
@app.route('/')
def index():
cur[0].execute("SELECT * from product")
resultProduct = cur[0].fetchall()
return render_template('index1.html', resultProduct=resultProduct)
@app.route('/input-pages', methods=['GET', 'POST'])
def inputPages():
if request.method == "GET":
return render_template("inputPage.html")
# ambil data dari form add product
name = request.form["name"]
price = request.form["price"]
stock = request.form["stock"]
# input ke database
cur[0].execute("INSERT INTO product values ((%s),(%s),(%s),(%s))",
(None, name, price, stock,))
cur[1].commit()
return redirect('/')
@app.route('/product/update', methods=['GET', 'POST'])
def productUpdates():
product_id = request.args['id']
if request.method == 'GET':
cur[0].execute("SELECT * from product WHERE id = %s", (product_id,))
result = cur[0].fetchone()
return render_template("updatePage.html", result=result)
# ambil data dari form edit product
name = request.form["name"]
price = request.form["price"]
stock = request.form["stock"]
# Get , while rule reques method is POST
cur[0].execute("UPDATE product SET name= (%s), price= (%s), stock= (%s)"
"Where id= (%s)",
(name, price, stock, product_id))
return redirect("/")
updatePage.html
{% extends "base.html" %}
{% block title %} Update Page {% endblock %}
{% block content %}
<div class="col-md-4">
</div>
<div class="col-md-4">
<div class="panel panel-danger">
<div class="panel-heading">
<center><h3><strong>Update Product</strong></h3></center>
</div>
<div class="panel-body">
<form action="" method="post">
<div class="form-group">
<label for="name">Name</label>
<input name="name" type="text" class="form-control" id="name" placeholder="Name" value="{{result[1]}}">
</div>
<div class="form-group">
<label for="price">Price</label>
<input name="price" type="text" class="form-control" id="price" placeholder="Price" value="{{result[2]}}">
</div>
<div class="form-group">
<label for="stock">Stock</label>
<input name="stock" type="text" class="form-control" id="stock" placeholder="Stock" value="{{result[3]}}">
</div>
<center><button type="submit" class="btn btn-danger">Submit</button></center>
</form>
</div>
</div>
</div>
<div class="col-md-4">
</div>
{% endblock %}
dan kita menambahkan hyperlink pada index.html untuk edit data,
{% for item in resultProduct %}
<tr>
<td>{{ loop.index }}</td>
<td>{{item[0]}}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
<td>{{ item[3] }}</td>
<td>
<a href="/product/update?id={{ item[0] }}" class="glyphicon glyphicon-pencil" aria-hidden="true">edit</a>
<a href="/product/delete?id={{ item[0] }}" class="glyphicon glyphicon-trash
">delete</a>
sehingga file index.html menjadi ,
{% extends 'base.html' %}
{% block title %} Index {% endblock %}
{% block content %}
{% if resultProduct %}
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="panel-title">
<center><h1>Daftar Barang</h1></center>
</div>
</div>
<div class="panel-body">
<div class="table-responsive">
<table class="table table-hover ">
<thead>
<th>No</th>
<th>ID Barang</th>
<th>Nama Barang</th>
<th>Harga Barang</th>
<th>Stok Barang</th>
<th>Action</th>
</thead>
<tbody>
{% for item in resultProduct %}
<tr>
<td>{{ loop.index }}</td>
<td>{{item[0]}}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
<td>{{ item[3] }}</td>
<td>
<a href="/product/update?id={{ item[0] }}" class="glyphicon glyphicon-pencil" aria-hidden="true">edit</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<center></center>
</div>
</div>
</div>
</div>
<div class="col-md-3">
</div>
</div>
{% endif %}
{% endblock %}
Yang terakhir kita akan membuat fungsi untuk mendelete data, perhatikan file index.html
tambahkan tag berikut pada block perulangan,
{% for item in resultProduct %}
<tr>
<td>{{ loop.index }}</td>
<td>{{item[0]}}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
<td>{{ item[3] }}</td>
<td>
<a href="/product/update?id={{ item[0] }}" class="glyphicon glyphicon-pencil" aria-hidden="true">edit</a>
<a href="/product/delete?id={{ item[0] }}" class="glyphicon glyphicon-trash
">delete</a>
sehingga file index.html kita menjadi,
{% extends 'base.html' %}
{% block title %} Index {% endblock %}
{% block content %}
{% if resultProduct %}
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="panel-title">
<center><h1>Daftar Barang</h1></center>
</div>
</div>
<div class="panel-body">
<div class="table-responsive">
<table class="table table-hover ">
<thead>
<th>No</th>
<th>ID Barang</th>
<th>Nama Barang</th>
<th>Harga Barang</th>
<th>Stok Barang</th>
<th>Action</th>
</thead>
<tbody>
{% for item in resultProduct %}
<tr>
<td>{{ loop.index }}</td>
<td>{{item[0]}}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
<td>{{ item[3] }}</td>
<td>
<a href="/product/update?id={{ item[0] }}" class="glyphicon glyphicon-pencil" aria-hidden="true">edit</a>
<a href="/product/delete?id={{ item[0] }}" class="glyphicon glyphicon-trash
">delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<center></center>
</div>
</div>
</div>
</div>
<div class="col-md-3">
</div>
</div>
{% endif %}
{% endblock %}
sedangkan pada views.py, kita menambahkan method product_delete, sehingga file views.py menjadi,
from flask import Flask, render_template, request, redirect
import MySQLdb as con
app = Flask(__name__, static_url_path='')
def GetConnection(): # method connections
connection = con.connect('127.0.0.1', 'root', '', 'pos')
cursor = connection.cursor()
return cursor, connection
cur = GetConnection()
@app.route('/')
def index():
cur[0].execute("SELECT * from product")
resultProduct = cur[0].fetchall()
return render_template('index1.html', resultProduct=resultProduct)
@app.route('/input-pages', methods=['GET', 'POST'])
def inputPages():
if request.method == "GET":
return render_template("inputPage.html")
# ambil data dari form add product
name = request.form["name"]
price = request.form["price"]
stock = request.form["stock"]
# input ke database
cur[0].execute("INSERT INTO product values ((%s),(%s),(%s),(%s))",
(None, name, price, stock,))
cur[1].commit()
return redirect('/')
@app.route('/product/update', methods=['GET', 'POST'])
def productUpdates():
product_id = request.args['id']
if request.method == 'GET':
cur[0].execute("SELECT * from product WHERE id = %s", (product_id,))
result = cur[0].fetchone()
return render_template("updatePage.html", result=result)
# ambil data dari form edit product
name = request.form["name"]
price = request.form["price"]
stock = request.form["stock"]
# Get , while rule reques method is POST
cur[0].execute("UPDATE product SET name= (%s), price= (%s), stock= (%s)"
"Where id= (%s)",
(name, price, stock, product_id))
return redirect("/")
@app.route("/product/delete")
def product_delete():
"""Delete product"""
product_id = request.args['id']
cur[0].execute("SELECT * from product WHERE id = %s", (product_id,))
result = cur[0].fetchone()
if result:
# delete product by id
cur[0].execute("DELETE FROM product WHERE id = %s ", (product_id,))
return redirect("/")
app.debug = True
app.run()
test koment. wkwk