Frontend untuk si Backend - Django Unicorn PART 1
Dalam tulisan ini saya fokus di akhir tulisan bisa membuat "crud" menggunakan django unicorn, jadi saya tidak akan membahas bagaimana membuat struktur template di django, saya pernah menulisnya di sini dan di sini.
Tujuan di sini akan membuat kontak form yang akan menerapkan
- inline validation
- form validation tanpa reload
- auto search di tabel
Pertama mari install dulu django unicorn (selanjutnya kita sebut saja unicorn), saya menggunakan pipenv, kalian bisa menggunakan tool favorit kalian masing-masing
Mari lihat dulu struktur folder django saya
.
├── contact
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── core
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── db.sqlite3
├── manage.py
├── Pipfile
├── Pipfile.lock
└── templates
└── layout.html
Penjelasan
- Saya memiliki sebuah project django dengan nama "core"
- Saya memiliki satu "app" dengan nama "contact"
- Saya membuat template untuk layout terpusat di folder "templates"
Konfigurasi
Karena tadi sudah memasang django unicorn sekarang saatnya kita mendaftarkan paket ini di django, ubah core/settings.py
di bagian INSTALLED_APPS
INSTALLED_APPS = [
...
"contact",
"django_unicorn",
]
Daftarkan pula urls untuk unicorn di core/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("unicorn/", include("django_unicorn.urls")),
]
Lalu di bagian templates/layout.html
pastikan kita sudah pasang script unicorn
{% load unicorn %}
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
{% unicorn_scripts %}
<style>
[unicorn\:error\:invalid] {
border: 1px solid red !important;
}
[unicorn\:error\:required] {
border: 1px solid red !important;
}
</style>
</head>
<body>
<main class="container">
{% csrf_token %}
{% block content %}
{% endblock %}
</main>
</body>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
<script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</html>
Penjelasan
- Baris pertama saya melakuan "load" untuk unicorn
- Menambahkan css untuk unicorn error
- Selanjutnya saya juga memastikan bahwa unicorn script sudah terpasang
- Pastikan
csrf_token
terpasang - Membuat blok
content
untuk memastikan bagian tersebut dinamis sesuai page yang diakses - Sisanya hanya cdn javascript dan css untuk kebutuhan dasar
Terminologi
Unicorn meyebut fiturnya dengan komponen, komponen ini terbagi ke dalam 2 bagian:
- komponen views
- komponen html
Komponen views ini mirip dengan views di django pada umumnya, berisi fungsi yang akan kita trigger, bedanya adalah fungsi di dalam komponen views itu bisa langsung dipanggil melalui komponen html tanpa perlu melakukan reload page, sederhananya komponen html saat memanggil fungsi komponen views secara otomatis melakukan ajax call, bedanya yang di-return tak hanya json tapi bisa dibilang satu komponen html.
Sebelum membuat komponen mari buat halaman untuk mencoba, karena kita akan buat kontak form dan list kontak yang terdaftar, mari buat halaman untuk dua hal tersebut, ini belum ada kaitannya dengan unicorn, ini masih django biasa
// contact/views.py
from django.shortcuts import render
def list_contact(request):
return render(request, "list.html")
def form_contact(request, id=None):
context = {"id": id}
return render(request, "form.html", context)
// contact/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("list", views.list_contact, name="list-contact"),
path("form/", views.form_contact, name="add-form"),
path("form/<int:id>", views.form_contact, name="edit-form"),
]
//core/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("contact.urls")),
path("unicorn/", include("django_unicorn.urls")),
]
lalu buat dua berkas di contact/templates/
yaitu list.html
dan form.html
//contact/templates/form.html
{% extends "layout.html" %}
{% load unicorn %}
{% block content %}
<section class="mb-4">
Komponen form akan di sini
</section>
{% endblock %}
//contact/templates/list.html
{% extends "layout.html" %}
{% load unicorn %}
{% block content %}
<section class="mb-4">
Komponen list akan di sini
</section>
{% endblock %}
Komponen
Sebelum masuk crud, mari bermain-main dengan komponen dan action unicorn, mari buat list komponen terlebih dahulu dengan perintah
//format
{{ ./manage.py startunicorn nama-app nama-komponen }}
./manage.py startunicorn contact list-contact
Perintah di atas akan menghasilkan dua berkas
contact/templates/list-contact.html
contact/components/list_contact.py
contact/
├── admin.py
├── apps.py
├── components
│ ├── __init__.py
│ ├── list_contact.py
├── __init__.py
├── migrations
│ ├── 0001_initial.py
│ └── __init__.py
├── models.py
├── templates
│ ├── form.html
│ ├── list.html
│ └── unicorn
│ ├── list-contact.html
├── tests.py
├── urls.py
└── views.py
Mari buka list_contact.py
isinya default seperti ini
from django_unicorn.components import UnicornView
class ListContactView(UnicornView):
pass
Lalu tambahkan seperti ini
from django_unicorn.components import UnicornView
class ListContactView(UnicornView):
name: str=""
Dan isi dari contact/templates/list-contact.html
seperti berikut
<div>
<input unicorn:model="name" type="text" class="form-control" />
<h2 class="h1-responsive font-weight-bold text-center my-4">{{ name | upper }}</h2>
</div>
Penting: dalam komponen html pastikan hanya ada satu container yang membungkus
Lalu di html list view biasa kita panggil komponen list-contact
{% extends "layout.html" %}
{% load unicorn %}
{% block content %}
<section class="mb-4">
<!--Section heading-->
<h2 class="h1-responsive font-weight-bold text-center my-4">Contact us</h2>
{% unicorn 'list-contact'%}
</section>
{% endblock %}
Hasilnya
Penjelasan
Pada bagian komponen html di input, di sana ada atribut kustom bernama unicorn:model="name"
bagian ini lah yang membuat inputan ini terkoneksi secara langsung ke properti name
di dalam class ListContactView
, karena kita tidak mendefinisikan trigger-nya secara otomatis untuk di input ini akan langsung dieksekusi saat ada ketikan, jika dibandingkan dengan javascript ini mirip dengan onkeyup
Action
Selain binding langsung dengan properti, komponen html bisa langsung berinteraksi dengan fungsi di dalam class, tambahkan fugsi di dalam class
from django.utils import timezone
from django_unicorn.components import UnicornView
class ListContactView(UnicornView):
name: str=""
def get_time(self):
current = timezone.now()
self.name = current.strftime("%H:%M:%S")
Di dalam komponen html, tambahkan tombol untuk memanggil fungsi yang sudah dibuat
<div>
<input unicorn:model="name" type="text" class="form-control" />
<h2 class="h1-responsive font-weight-bold text-center my-4">{{ name | upper }}</h2>
<button unicorn:click="get_time" class="btn btn-info">Today</button>
</div>
Hasilnya
Penjelasan
Dalam view saya membuat fungsi get_time
dan di komponen html di dalam button saya menambahkan trigger unicorn:click=get_time
, jika dibandingkan dengan javascript ini mirip dengan onclick
Fungsi dengan parameter
Mari ubah dulu fungsi agar bisa menampung parameter
from datetime import timedelta
from django.utils import timezone
from django_unicorn.components import UnicornView
class ListContactView(UnicornView):
name: str = ""
def get_time(self, hour=None):
current = timezone.now()
if hour:
current = current + timedelta(hours=hour)
self.name = current.strftime("%H:%M")
Dan komponen html
<div>
<h1> Sekarang jam {% now "H:i" %} </h1>
<input unicorn:model="name" type="text" class="form-control" />
<h2 class="h1-responsive font-weight-bold text-center my-4">{{ name | upper }}</h2>
<button unicorn:click="get_time" class="btn btn-info">Today</button>
<button unicorn:click="get_time(2)" class="btn btn-info">Add 2 hour</button>
<button unicorn:click="get_time(3)" class="btn btn-info">Add 3 hour</button>
<button unicorn:click="get_time(4)" class="btn btn-info">Add 4 hour</button>
</div>
Hasilnya
Oke, di part 1 ini selesai dulu sebagai perkenalan dengan unicorn, di tulisan selanjutnya baru kita membuat crud.