Membangun Minimum Viable Product Dengan Flask Dan Tailwind

Muhammad Syukur Abadi
6 min readJul 11, 2021

--

Photo by HalGatewood.com on Unsplash

Pendahuluan

Beberapa waktu lalu, saya sempat bercerita tentang bagaimana saya bangkit dari kegagalan dengan mengikuti Bootcamp HackGov 2021 yang diadakan oleh BEM KM UGM. Di tulisan tersebut, saya bercerita bahwa kami membuat minimum viable product (MVP) berupa sistem informasi berbasis web yang kami beri nama Kawal Pembangunan. Di tulisan tersebut juga, saya bercerita bahwa web tersebut dibangun menggunakan framework Flask untuk backend dan TailwindCSS untuk frontend. Pada artikel ini, saya akan membahas bagaimana web Kawal Pembangunan dibuat, harapannya lewat tulisan ini, pembaca dapat menambah wawasan tentang web development. Tidak hanya itu, saya juga berharap lewat tulisan ini, kita sama-sama bisa berdiskusi bagaiamana project ini seharusnya disusun dan best practice clean code pada project ini dibuat.

Sebelum ke pembahasan, saya ingin sedikit bercerita mengapa saya ingin menggabungkan Flask dengan Tailwind. Pertama, alasan saya memilih Flask karena Flask cocok untuk project skala kecil, dan alasan saya memilih Tailwind karena kustomisasi komponen-komponen web dapat dibuat lebih bebas. Kedua, saya pernah membuat web menggunakan Flask (web tersebut bisa diakses di sini), namun web tersebut tidak menggunakan database sama sekali. Saya ingin menantang diri saya sendiri untuk menggabungkan Flask dengan Tailwind, serta membuat database pada MVP yang akan kami buat.

Kode lengkap dari MVP ini bisa dilihat di sini.

Setup

Seperti yang telah dijelaskan di atas, MVP dibuat menggunakan Flask dan Tailwind. Saya menggunakan tutorial dari https://testdriven.io/blog/flask-htmx-tailwind/. Langkah-langkah pada web tersebut cukup jelas (setidaknya untuk saya) untuk mengintegrasikan Tailwind dengan Flask.

Hal pertama yang kita lakukan adalah memastikan Python dan NodeJS sudah ter-install beserta environment variable dari Python sudah di-set. Selanjutnya, membuat direktori project, membuat virtual environment, dan install dependensi, yakni Flask dan Flask-Assets

Sumber https://testdriven.io/blog/flask-htmx-tailwind/

Pada baris pertama, kita membuat direktori project, pada baris kedua, kita membuat virtual environment, dan kita aktifkan pada baris ketiga. Baris kelima muncul ketika virtual environment berhasil dijlankan. Kita meng-install dependensi pada baris terakhir. Kemudian, install Tailwind menggunakan command (keluar dari virtual environment terlebih dahulu).

Sumber https://testdriven.io/blog/flask-htmx-tailwind/

Selanjutnya, buat file app.py dengan isi file sebagai berikut

Sumber https://testdriven.io/blog/flask-htmx-tailwind/

Kemudian, jalankan command di bawah untuk men-generate file tailwind.config.js, di mana file tersebut adalah file konfigurasi dari Tailwind.

Sumber https://testdriven.io/blog/flask-htmx-tailwind/

Selanjutnya, kita buat file postcss.config.js dengan meng-copy snippet di bawah.

Sumber https://testdriven.io/blog/flask-htmx-tailwind/

Selanjutnya, buat folder baru dengan nama static yang di dalamnya terdapat folder src. Lalu, buatlah file main.css di dalam folder src, kemudian copy snippet berikut.

Sumber https://testdriven.io/blog/flask-htmx-tailwind/

Kemudian, aktifkan virtual environment menggunakan perintah venv/Scripts/activate pada terminal dan jalankan file app.py menggunakan perintah python app.py pada terminal. Setelah perintah python app.py berhasil dijalankan, pada folder static terdapat folder dist yang berisi file main.css.

Struktur folder dari langkah-langkah di atas sebagai berikut

Database

Sebelum membahas bagaimana desain HTML serta Tailwind, saya akan menjelaskan bagaimana membuat database terlebih dahulu, sebab pada file HTML nanti, kita langsung bisa mengakses data yang ada pada database menggunakan jinja syntax.

Pada MVP ini, data-data yang akan disimpan pada database mengambil beberapa atribut dari tender dengan kategori pekerjaan konstruksi pada situs LPSE Provinsi Jawa Timur.

Situs LPSE Provinsi Jawa Timur

Jika kita memilih salah satu dari pilihan tender yang ada, kita akan menuju halaman berikut

Detail salah satu tender

Kita membutuhkan package flask-sqlalchemy yang merupakan package terpisah dari package flask. Untuk men-download package tersebut, kita lakukan download menggunakan pip install flask-sqlalchemy pada virtual environment.

Pada MVP ini kita akan membuat dua buah tabel : tabel sektor dan tabel pembangunan sektor. Tabel sektor digunakan untuk menampung data sektor, misalnya sektor pendidikan, sektor industri, dan sektor perikanan, sedangkan tabel pembangunan sektor digunakan untuk menampung detail tender seperti gambar di atas. Atribut yang digunakan pada tabel sektor adalah alias sektor serta nama sektor, sedangkan atribut yang digunakan pada tabel pembangunan adalah kode tender, nilai HPS, nama tender, kualifikasi usaha, beserta syarat kualifikasi. Berikut source code untuk membangun instance database beserta tabel. Source code di bawah ditulis di dalam file app.py

Pada baris ke-20, kita mendefinisikan relasi (relationship) antara tabel sektorTable dengan tabel pembangunanSektorTable menggunakan method relationship. Method tersebut memiliki dua parameter, yakni tabel yang akan direlasikan, dan backref sebagai pseudo-column pada tabel sektorTable. Pada baris ke-33 kita mendefinisikan kolom relasi_sektor sebagai foreign key dari atribut id pada tabel sektorTable. Relasi ini bersifat one to many yang artinya satu sektor pembangunan dapat memiliki banyak tender, misalnya pada sektor perikanan, terdapat pembangunan dengan nama tender A, B, C, dan D, dan pada sektor pendidikan terdapat pembangunan dengan nama tender E, F, dan G. Relasi tersebut tidak memungkinkan satu tender dimiliki oleh satu sektor.

Untuk menambahkan data ke dalam tabel, kita harus masuk ke python terminal dengan menggunakan perintah berikut:

Untuk membuat tabel, lanjutkan dengan perintah berikut

Jika perintah di atas berhasil dieksekusi, maka teman-teman akan menemukan file database pada direktori yang sama dengan file app.py dengan nama proyek.db.

Untuk menambah data pada tabel, kita harus melakukan import pada file yang memiliki class tabel. Snippet di bawah ini merupakan contoh menambahkan record pada tabel pembangunanSektorTable. Untuk menambahkan data pada tabel sektorTable, perintah yang diketik sama.

Setelah data berhasil ditambah, kita lakukan commit pada session. Jika teman-teman tidak melakukan commit, data yang ditambahkan tidak akan tertulis di database. Untuk melakukan commit pada session, ketikkan perintah berikut.

Routes

Routes digunakan untuk melakukan fetch data dari database, serta mengirimkan data yang telah di-fetch ke dalam templates. Berikut salah satu route

Pada baris ke-3 dan ke-4, kita melakukan query pada tabel sektorTable dan kerjasamaTable. Hasil query tersebut masing-masing disimpan pada variabel sektor dan instansi. Pada baris ke-5, kita melakukan render template menggunakan fungsi render_template(). Parameter fungsi tersebut berisi template atau view, dan parameter sisanya adalah data yang dikirim ke view tersebut. Data yang dikirim pada view index.html adalah sektor dan instansi. Untuk mengakses route yang telah kita buat, kita jalankan terlebih dahulu file app.py, dan tambahkan /home dibelakang URL.

Berikut contoh routing untuk data dengan nilai spesifik

Pada baris pertama, parameter dari decorator route adalah /sektor/<sektor>, yang berarti <sektor> adalah nilai spesifik dari kode sektor (selengkapnya akan dibahas pada bagian templates). Untuk mengakses sektor tertentu dari kode sektor yang spesifik, kita lakukan query sesuai kode sektor yang diinginkan seperti yang tertulis pada baris ke-3. Variabel sektor akan berisi query dengan record sektor sesuai id sektor yang diinginkan.

Keseluruhan route disimpan pada file app.py. Berikut kode lengkap untuk file app.py.

Templates

Tahap terakhir adalah menyusun view atau template. Flask menggunakan jinja syntax untuk melakukan menyusun template dan mengirim data ke template. Kita mendefinisikan base template sebagai berikut.

Pada baris ke-9 sampai baris ke-11, kita mendefinisikan jinja untuk assets yang memuat dependensi Tailwind. Pada baris ke-22, ke-27, dan ke-30, terdapat url_for dengan yang akan mengarahkan ke route. Pada baris ke-37 sampai baris ke-39, terdapat block content, di mana block tersebut berisi konten sesuai halaman atau page yang akan kita buat. Berikut ini adalah contoh penggunaan block content pada halaman index di bawah.

Pada baris pertama kode di atas, kita melakukan extends base.html, ini berarti file index.html menggunakan base.html sebagai base template. Satu file hanya bisa menggunakan atau meng-extends satu base template.

Untuk memasukkan nilai pada url, kita bisa melakukannya seperti pada baris ke-34, di mana parameter kedua dari url_for() adalah nilai yang akan diambil oleh route sektor. Isi route tersebut sebagai berikut.

Mari kita ingat kembali, kita telah mengirim data berisi query pada tabel sektorTable dan tabel kerjasamaTable pada route home.

Pada file index.html di atas, kita mengakses data dari sektor dan instansi menggunakan jinja syntax untuk for dan if. Berikut hasil dari template index.html.

Konklusi

Project ini adalah project perdana saya membuat aplikasi web menggunakan Flask dan Tailwind. Pada project ini juga, saya menghadapi beberapa kendala, seperti mengakses record pada database, membuat ulang project karena variabel atau instance tidak ada setelah dilakukan project restructure, serta error berkali-kali ketika mengkases nilai dari hasil query pada template/view. Saya belajar banyak dari project ini, di mana project ini tidak hanya mengasah saya untuk berpikir cepat dan tidak mudah menyerah, tetapi juga mendengarkan orang lain serta tidak besar kepala.

--

--

Muhammad Syukur Abadi

Ordinary computer science student and a gundam geek. Also hugging psychology, math, and physics stuffs. I can be reached on my instagram @sykrabadi