Dalam tulisan sebelumnya sudah mencoba fungsi-fungsi dasar unicorn, dalam kali ini akan buat untuk CRUD. Pertama mari buat bagian list.
list-contact.py
Berikut isi komponen list-contact.py
from django.shortcuts import redirect
from django_unicorn.components import LocationUpdate, QuerySetType, UnicornView
from contact.models import ContactForm
class ListContactView(UnicornView):
data: QuerySetType[ContactForm] = ContactForm.objects.none()
search: str = ""
def mount(self):
"""On mount, populate the movies property w/ a QuerySet of all movies"""
self.load_data()
def load_data(self, query=None):
datas = ContactForm.objects.all()
if query:
datas = datas.filter(name__icontains=query)
datas = datas.order_by("-id")
self.datas = datas
def updated_search(self, query):
self.load_data(query)
def delete(self, id):
ContactForm.objects.filter(id=id).delete()
self.mount()
self.reset()
Mari bahas perblok
data: QuerySetType[ContactForm] = ContactForm.objects.none()
search: str = ""
Properti atau variable untuk menampung data:
- data: Menampung untuk querysety dari contactform
- search: Menampung keyword search yang akan ditrigger dari komponen
list-contact.html
def mount(self):
"""On mount, populate the movies property w/ a QuerySet of all movies"""
self.load_data()
def load_data(self, query=None):
data = ContactForm.objects.all()
if query:
data = data.filter(name__icontains=query)
data = datas.order_by("-id")
self.data = data
def updated_search(self, query):
self.load_data(query)
Fungsi mount()
adalah fungsi bawaan dari unicorn yang akan dijalankan ketika komponen ini di-load
Fungsi load_data()
adalah fungsi yang dibuat untuk mencari data dari model terkait, ini bukan fungsi bawaan, ini yang dibuat sendiri
Fungsi updated_search()
adalah fungsi bawaan yang akan mendeteksi perubahan pada variable search, ini formatnya updated_<nama_variable>()
def delete(self, id):
ContactForm.objects.filter(id=id).delete()
self.mount()
self.reset()
Sesuai namanya ini fungsi untuk menghapus data dari contactForm, sedangkan untuk self.mount()
untuk memastikan data ke-refresh, sedangkan reset untuk mengambalikan ke state awal.
Untuk tampilannya bbah komponen list-contact.html
menjadi seperti berikut:
<div>
<div class="float-right mb-4">
<a href="{% url 'add-form' %}" class="btn btn-success"> Add Form </a>
</div>
<!--Section: Contact component list-->
<div class="row ">
<div class="col-4">
<input unicorn:model="search" type="text" id="myInput" class="form-control" placeholder="Search for names..">
</div>
</div>
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{% for single in data %}
<tr>
<td>{{ single.name }}</td>
<td>{{ single.email }}</td>
<td>
<a class="btn btn-success" href="{% url 'edit-form' id=single.id %}">Update</a>
<button class="btn btn-danger"
onclick="swal.fire({
icon: 'warning',
title: 'Are you sure??',
text: 'data deleted permanently!!',
showCancelButton: true,
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
}).then((result) => {
if (result.isConfirmed) {
Unicorn.call('list-contact', 'delete', '{{ single.id}}')
}
})">
Delete</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
Mari bahas "perbaris"
Pertama
<div class="float-right mb-4">
<a href="{% url 'add-form' %}" class="btn btn-success"> Add Form </a>
</div>
Ini masih django template sederhana, itu sebuah link untuk menuju path add-form
alias untuk menambahkan kontak form
Pastikan url atau views tujuan sudah disiapkan, sengaja gak bahas itu karena itu tidak ada sangkut pautnya langsung dengan unicorn
<div class="col-4">
<input unicorn:model="search" type="text" id="myInput" class="form-control" placeholder="Search for names..">
</div>
kode di atas mirip dengan di tulisan sebelumnya, melakukan request langsung ke komponen list-contact.py
{% for single in data %}
<tr>
<td>{{ single.name }}</td>
<td>{{ single.email }}</td>
<td>
<a class="btn btn-success" href="{% url 'edit-form' id=single.id %}">Update</a>
<button class="btn btn-danger"
onclick="swal.fire({
icon: 'warning',
title: 'Are you sure??',
text: 'data deleted permanently!!',
showCancelButton: true,
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
}).then((result) => {
if (result.isConfirmed) {
Unicorn.call('list-contact', 'delete', '{{ single.id}}')
}
})">
Delete</button>
</td>
</tr>
{% endfor %}
Itu looping biasa, bedanya data
datang dari list-contact.py
dan pada bagian onclick
saya memanggil swal untuk modal confirm sedangkan Unicorn.call('list-contact', 'delete', '{{ single.id}}')
Ini fungsi dari unicorn yaitu bisa memanggil langsung method di list-contact.py
dari javascript.
Sedangkan untuk bagian href="{% url 'edit-form' id=single.id %}
ini fungsi url django standar, mengirimkan ke url path edit form dengan param id dari data yang dipilih.
Sehingga hasilnya seperti berikut
![](http://arsmp.com/content/images/2022/07/Screenshot-from-2022-07-20-21-24-49.png)
Form
Sama dengan sebelumnya perlu buat dulu komponen baru, saya beri nama form-contact
sehingga menghasilkan form-contact.py
dan form-contact.html
form-contact.py
from django import forms
from django.shortcuts import redirect
from django_unicorn.components import QuerySetType, UnicornView
from contact.models import ContactForm
class FormContact(forms.Form):
contact_id = forms.IntegerField(required=False)
name = forms.CharField(max_length=100, required=True)
email = forms.EmailField(max_length=100, required=True)
text = forms.Textarea()
def clean(self):
cleaned_data = super().clean()
email = cleaned_data.get("email")
pk = cleaned_data.get("contact_id")
if email:
exist = ContactForm.objects.filter(email=email).first()
if exist:
if exist.id != pk:
self.add_error("email", "email already used")
class FormContactView(UnicornView):
form_class = FormContact
name = ""
email = ""
text = ""
contact_id = None
def mount(self):
"""On mount, populate the movies property w/ a QuerySet of all movies"""
if self.contact_id:
self.populate(self.contact_id)
def populate(self, id):
detail = ContactForm.objects.get(id=id)
self.name = detail.name
self.email = detail.email
self.text = detail.text
self.contact_id = id
def submit(self):
collect = {"name": self.name, "email": self.email, "text": self.text}
if self.is_valid():
if self.contact_id:
contact = ContactForm.objects.get(id=self.contact_id)
contact.name = self.name
if contact.email != self.email:
contact.email = self.email
contact.text = self.text
else:
contact = ContactForm(**collect)
contact.save()
return redirect("list-contact")
Kembali bahas perblok
class FormContact(forms.Form):
contact_id = forms.IntegerField(required=False)
name = forms.CharField(max_length=100, required=True)
email = forms.EmailField(max_length=100, required=True)
text = forms.Textarea()
def clean(self):
cleaned_data = super().clean()
email = cleaned_data.get("email")
pk = cleaned_data.get("contact_id")
if email:
exist = ContactForm.objects.filter(email=email).first()
if exist:
if exist.id != pk:
self.add_error("email", "email already used")
Tidak ada yang aneh di bagian ini, ini hanyalah django forms pada umumnya, tidak spesifik django unicorn
form_class = FormContact
name = ""
email = ""
text = ""
contact_id = None
- form_class = Variable "bawaan" untuk identifikasi bahwa django unicorn akan mengunkana django form yang mana
- name = Variable yang akan menampung "name"
- email = Variable yang akan menampung "email"
- text = Variable ayng akan menampung "text"
- contact_id = Variable yang akan menampung id
def mount(self):
"""On mount, populate the movies property w/ a QuerySet of all movies"""
if self.contact_id:
self.populate(self.contact_id)
def populate(self, id):
detail = ContactForm.objects.get(id=id)
self.name = detail.name
self.email = detail.email
self.text = detail.text
self.contact_id = id
Sama seperti sebelumnya, mount()
, sedangkan populate()
untuk populas data jika id diberikan saat initialisasi komponent
def submit(self):
collect = {"name": self.name, "email": self.email, "text": self.text}
if self.is_valid():
if self.contact_id:
contact = ContactForm.objects.get(id=self.contact_id)
contact.name = self.name
if contact.email != self.email:
contact.email = self.email
contact.text = self.text
else:
contact = ContactForm(**collect)
contact.save()
return redirect("list-contact")
Fungsi submit()
standar gak ada yang aneh, untuk insert data jika tidak ada contact_id
dan update jika ada.
Lalu di form-contact.html
<div>
<!--Section: Contact v.2-->
<section class="mb-4">
<!--Section heading-->
<h2 class="h1-responsive font-weight-bold text-center my-4">Contact us</h2>
<div class="row">
<!--Grid column-->
<div class="col-md-12 mb-md-0 mb-5">
<!--Grid row-->
<div class="row">
<!--Grid column-->
<div class="col-md-6">
<div class="md-form mb-0">
<span class="error">{{ unicorn.errors.name.0.message }}</span>
<input unicorn:model="contact_id" type="hidden" id="id" name="id" class="form-control">
<input unicorn:model="name" type="text" id="name" name="name" class="form-control">
<label for="name" class="">Your name {{ name }}</label>
</div>
</div>
<!--Grid column-->
<!--Grid column-->
<div class="col-md-6">
<div class="md-form mb-0">
<span class="error">{{ unicorn.errors.email.0.message }}</span>
<input unicorn:model="email" type="email" id="email" name="email" class="form-control">
<label for="email" class="">Your email {{ email }} </label>
</div>
</div>
<!--Grid column-->
</div>
<!--Grid row-->
<!--Grid row-->
<div class="row">
<!--Grid column-->
<div class="col-md-12">
<div class="md-form">
<textarea unicorn:model="text" type="text" id="message" name="message" rows="2" class="form-control md-textarea"></textarea>
<label for="message">Your message</label>
</div>
</div>
</div>
<!--Grid row-->
<div class="text-center text-md-left">
<button class="btn btn-success" unicorn:click="submit">Submit</button>
<a class="btn btn-warning" href={% url 'list-contact'%}>Cancel</a>
</div>
<div class="status"></div>
</div>
<!--Grid column-->
</div>
</section>
</div>
Di sini cukup to the point, di mana setiap field di html di atas binding dengan setiap variable di form-contact.py
Yang sedikit beda cara panggilnya
{% unicorn 'form-contact' contact_id=id%}
Perintah di atas saat inisialisasi komponen akan sekalian mengirimkan nilai dari "contact_id".
Hasil akhirnya
![](http://arsmp.com/content/images/2022/07/Peek-2022-07-20-21-48.gif)
Fungsi di atas langsung bekerja dengan baik kan termasuk validasi saat nulis email, itu dia akan langsung membaca ke django forms yang ditulis sebelumnya.
Dan ini hasil akhirnya
![](http://arsmp.com/content/images/2022/07/Peek-2022-07-20-21-51.gif)
Sampai jumpa di tulisan lain lagi.