Setelah kita membahas tentang membuat aplikasi Flask dengan mysql secara native, disini kita akan membahas tentang aplikasi Flask dengan mysql menggunakan ORM. apa itu ORM?
ORM singkatan dari Object Relational Mapping. ORM adalah metode/teknik pemrograman yang digunakan untuk mengkonversi data dari lingkungan database relasional menjadi berorientasi objek (OOP). ORM bertugas sebagai penghubung dengan DBMS.
Ada banyak manfaat dengan menggunakan ORM, antara lain:
- Memisahkan layer programming dengan kode SQL
- Mempermudah Maintenance jika terjadi perubahan DBMS
- Mengurangi perulangan kode query
- Membuat akses data menjadi lebih abstrak dan portable
- Mengenerate boilerplate code (unit kode yang reusable) untuk fungsi dasar CRUD (Create, Read, Update, Delete).
Salah satu ORM yang cukup banyak dipakai di Python adalah SQLAlchemy. Pada artikel ini, kita akan membuat aplikasi blog menggunakan Flask dan SQLAlchemy
Persiapan install requirement system
Sebelum membuat program, pastikan kita menginstall library2 yang digunakan. Disini kita akan menggunakan Flask, Flask-SQLAlchemy dan PyMySQL.
$ pip install flask flask-sqlalchemy pymysql
Untuk menggunakan SQLAlchemy dan PyMysql kita harus mengincludekan pada file app.py seperti berikut.
from flask import Flask, render_template, request from flask_sqlalchemy import SQLAlchemy from sqlalchemy import desc, and_, func from env import * app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://' + db_user + ':' + db_password + '@' + db_host + '/' + db_name app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app)
Modul env digunakan untuk menyimpan parameter koneksi mysql seperti db_user, db_password, db_host dan db_name. Isikan sesuai konfigurasi di komputer kita.
Membuat model Database
Pada aplikasi blog ini, kita akan membuat 3 table yaitu user, categories dan article. Dimana relasi antara user dan article adalah one to many. Sedangkan relasi antara kategori dan article juga one to many. Berikut desain model yang digunakan.
class Ci_users(db.Model):
id_user = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(30), unique=True, nullable=False)
nama = db.Column(db.String(100), nullable=False)
def __repr__(self):
return '{}|{}|{}'.format(self.username, self.nama, self.id_user)
class Ci_categories(db.Model):
id_kategori = db.Column(db.Integer, primary_key=True)
nama_kategori = db.Column(db.String(50), unique=True, nullable=False)
slug = db.Column(db.String(60), unique=True, nullable=False)
def __repr__(self):
return '{}|{}|{}'.format(self.nama_kategori, self.slug, self.id_kategori)
class Ci_posts(db.Model):
post_id = db.Column(db.Integer, primary_key=True)
post_title = db.Column(db.String(250), nullable=False)
post_slug = db.Column(db.String(300), nullable=False)
post_category = db.Column(db.Integer, db.ForeignKey('ci_categories.id_kategori'), nullable="False")
category_name = db.relationship('Ci_categories', backref=db.backref('Ci_posts', lazy=True))
post_author = db.Column(db.Integer, db.ForeignKey('ci_users.id_user'), nullable="False")
author = db.relationship('Ci_users', backref=db.backref('Ci_posts', lazy=True))
post_content = db.Column(db.Text)
post_date = db.Column(db.DateTime, default=datetime.datetime.utcnow())
def __repr__(self):
return '{}|{}|{}'.format(self.post_title, self.post_category, self.post_id)
Perhatikan bagaimana sql-alchemy mengimplementasikan foreign key dari bentuk DBMS ke bentuk ORM. Column post_author digunakan untuk menyimpan id_user. Column author digunakan untuk merefer nama user yang diambil dari fungsi __repr__ yang direturn oleh class user.
Menampilkan data pada browser
Pada artikel ini, kita akan menggunakan paginasi pada halaman yang ditampilkan. Jadi, semua data yang dimunculkan akan dilimit. Paginasi dengan Flask SQLAlchemy sangat mudah untuk diimplementasikan. Untuk menerapkan hal ini, kita perlu membuat routing terlebih dahulu, seperti berikut.
@app.route('/')
@app.route('/page/<int:i>/')
def index(i=1):
if request.path != '/':
page = int(request.path.split('/')[2])
else:
page = 1
article = Ci_posts.query.order_by(desc(Ci_posts.post_date)).paginate(page=page, per_page=per_page)
return render_template('index.html', data=article)
Skrip diatas membuat 2 routing yaitu index dan page. Default page pada halaman index kita set 1. Untuk mengambil parameter page, karena kita menggunakan url yang SEO friendly seperti https://www.article/page/1 maka kita perlu menggunakan fungsi split pada variabel request.path.
Selanjutnya nilai page kita jadikan parameter untuk mengambil data article. Hasil pengambilan datanya kita kirimkan ke template dengan fungsi render_template. Fungsi paginate digunakan untuk membatasi data yang diambil menggunakan SQLAlchemy.
Paginasi data dengan SQLAlchemy
Tidak seperti cara biasanya yang menggunakan looping nama variabel, dengan paginasi kita menggunakan properti variabel.elemen untuk melooping data yang ditampilkan. Berikut script jinja2 untuk menampilkan data yang sudah dipaginasi.
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center">
<li class="page-item {% if data.page == 1 %} disabled {% endif %}">
<a class="page-link" href="{{ url_for('index', i=data.prev_num) }}">Previous</a></li>
{% for page_num in data.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
{% if page_num %}
{% if data.page == page_num %}
<li class="page-item active">
<a class="page-link" href="{{ url_for('index', i=page_num) }}">{{ page_num }}</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="{{ url_for('index', i=page_num) }}">{{ page_num }}</a>
</li>
{% endif %}
{% else %}
...
{% endif %}
{% endfor %}
<li class="page-item {% if data.page == data.pages %}disabled{% endif %}">
<a class="page-link" href="{{ url_for('index', i=data.next_num) }}">Next</a>
</li>
</ul>
</nav>
Dengan paginate SQLAlchemy, kita tidak perlu membuat paginasi secara manual. Sudah ada fungsi built-in yang siap dipakai. Misalnya data.page yang menunjukkan halaman yang aktif, data.next_num yang menunjukkan halaman sebelumnya, data.prev_num yang menunjukkan halaman sesudah dan fungsi2 yang lain.
Error yang umum pada Flask SQL Alchemy
'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.'
Solusi: tambahkan baris berikut di app.py
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
Kesimpulan
Konektivitas database dari flask bisa dilakukan secara native maupun menggunakan ORM (Object Relational Mapping). Masing2 memiliki keunggulan tersendiri. Pemilihan ORM atau native sebaiknya disesuaikan dengan kondisi aplikasi yang akan dibuat. Selamat mencoba dan membandingkan performa dan kemudahan penggunaan koneksi native dan ORM.
Fullstack Developer yang tinggal di yogyakarta. Suka eksplorasi hal baru yang berhubungan dengan pemrograman dan ilmu keislaman. Berpengalaman dalam pemrograman PHP, Delphi dan sedang upgrade skill dengan python. Just as simple that.
1 thought on “Membuat aplikasi Flask dengan MySQL menggunakan SQL Alchemy”