Repositori tugas PBP
NAMA : Fadhil Muhammad
NPM : 2206083464
http://fadhil-muhammad23-tugas.pbp.cs.ui.ac.id/
Tugas 2
- Pengenalan
- Langkah-Langkah Pengimplementasian
- Diagram
- Mengapa Menggunakan Virtual Environment?
- Apa itu MVC, MVT, dan MVVM?
Tautan web: https://poke-co.adaptable.app/main
Poké.co merupakan website dengan tema utama pengumpulan atau pengoleksian karakter-karakter Pokémon yang dibangun menggunakan Django untuk tugas kali ini.
Dalam proses pembuatan website ini, hal pertama yang dilakukan adalah membuat repositori baru di github sebagai tempat penyimpanan hasil pekerjaan.
Setelah itu, step-step yang dilakukan antara lain:
-
Membuat Direktori Lokal Baru untuk Proyek Aplikasi
Langkah pertama adalah membuat direktori baru pada perangkat lokal sebagai direktori utama untuk pengerjaan proyek
-
Mengaktifkan Virtual Environment pada Direktori
Setelah direktori pada langkah pertama berhasil dibuat, selanjutnya menginisialisasi atau mengaktifkan virtual environment untuk proyek.
python -m venv env
Menjalankan perintah di atas pada command prompt untuk menginisialisasi virtual environment pada folder proyek.
-
Mengaktifkan Virtual Environment
Mengaktifkan virtual environment untuk direktori proyek dengan menjalankan script berikut pada command prompt.
env\Scripts\activate.bat
-
Menginstall Dependencies atau Requirements
Setelah virtual environment berhasil diaktifkan, membuat file baru pada direktori bernama
requirements.txt
dengan isi sebagai berikut:django gunicorn whitenoise psycopg2-binary requests urllib3
Setelah file
requirements.txt
berhasil dibuat, lalu install requirements atau dependencies tersebut dengan menjalankan script berikut pada command prompt.pip install -r requirements.txt
-
Membuat Proyek Django
Setelah semua dependencies terinstall, inisialisasi atau mulai proyek baru dengan menjalankan perintah berikut:
django-admin startproject poke_co .
-
Konfigurasi Proyek
Setelah proyek berhasil dibuat, langkah selanjutnya adalah mengkonfigurasi proyek. Hal yang dilakukan pada langkah ini di antaranya:
-
Menambahkan allowed host pada file
settings.py
... ALLOWED_HOSTS = ["*"] ...
-
Menambahkan direktori staticfiles dan static root pada
settings.py
untuk file-file statis seperti image... STATICFILES_DIRS = ( join(BASE_DIR, 'main/static'), ) STATIC_ROOT = join(BASE_DIR, 'staticfiles') ...
-
Mendaftarkan aplikasi
main
ke dalam proyek dengan menambahkan"main"
ke dalam daftar aplikasi yang ada padasettings.py
INSTALLED_APPS = [ ..., "main", ... ]
-
-
Membuat Template untuk Laman Website
Untuk menampilkan laman page yang diinginkan saat website dibuka, tambahkan sebuah folder baru pada direktori
main
bernamatemplates
, lalu dalam foldertemplates
tambahkanmain.html
.Dalam
main.html
, isi file tersebut dengan HTML yang diinginkan. Dalam proyek ini, contoh dari bagianbody HTML yang digunakan untuk proyek ini adalah sebagai berikut:... <section> <h2>Player Information</h2> <h5>Name:</h5> <p>{{ name }}</p> <h5>Class:</h5> <p>{{ class }}</p> </section> ...
Untuk selengkapnya dapat dilihat pada file
main.html
-
Konfigurasi untuk Gambar
Pada proyek ini, gambar digunakan untuk ditampilkan pada laman web. Agar gambar dapat ditampilkan pada saat production atau deployment:
-
Buat folder tempat penyimpanan file statis (untuk gambar). Tempat penyimpanan disesuaikan dengan
path
pengambilan gambar yang ada pada templatemain.html
dan konfigurasi yang ada padasettings.py
-
Agar gambar dapat diambil pada saat
deployment
, jalankan perintah berikut.python manage.py collectstatic
Akan terbentuk sebuah folder baru sebagai direktori file yang bisa diambil kontenya pada saat tahap deployment. Jika tidak menjalankan perintah tersebut, maka gambar kemungkinan tidak akan muncul pada saat deployment walaupun pada saat development secara lokal muncul.
-
Tidak lupa, tambahkan
{% load static %}
padamain.html
agar file statis dapat di-load.
-
-
Mengimplementasikan Model
pada langkah ini, modifikasi file
models.py
sesuai dengan kriteria soal dan aplikasi yang akan dibuat. Untuk proyek ini, isi darimodels.py
adalah sebagai berikut:from django.db import models class Item(models.Model): name = models.CharField(max_length=255, name="name") amount = models.IntegerField(name="amount") rarity = models.IntegerField(name="rarity", default=0) power = models.FloatField(name="power", default=0) description = models.TextField(name="description")
-
Membuat dan Mengaplikasikan Migrasi Model
Lakukan migrasi model dengan menjalankan perintah berikut pada Command Prompt agar Django dapat melacak perubahan pada model database.
python manage.py makemigrations python manage.py migrate
-
Menghubungkan View dengan Template
Menambahkan kode berikut pada
views.py
.from django.shortcuts import render def show_main(request): context = { 'name':'Fadhil Muhammad', 'class':'PBP-B', 'char_name':'Pikachu', 'char_description':'This is Pikachu. You know this is Pikachu. Why are you asking me about why i wrote this?', 'char_amount':'You have Gazillion amount of this character.' } return render(request, 'main.html', context)
Karena proyek aplikasi ini belum sepenuhnya dikembangkan, beberapa variable masih digunakan hanya sebagai place holder sementara.
-
Melakukan Routing URL
Agar aplikasi dapat dijalankan tambahkan kode berikut pada
urls.py
pada direktori proyekfrom django.contrib import admin from django.urls import path, include from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('main/', include('main.urls')), path('admin/', admin.site.urls), ] if settings.DEBUG: urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
dan kode berikut pada
urls.py
pada direktorimain
from django.urls import path from main.views import show_main app_name = 'main' urlpatterns = [ path('', show_main, name='show_main'), ]
-
Menambahkan Unit Testing
Untuk menguji website, dilakukan beberapa unit testing dasar untuk menguji apakah website berhasil ter-load dengan baik atau tidak dengan menambahkan kode pada tests.py sesuai dengan pengujian yang ingin dilakukan. Untuk proyek ini:
from django.test import TestCase from django.test import Client class mainTest(TestCase): def test_main_url_is_exist(self): client = Client() response = client.get('/main/') self.assertEqual(response.status_code, 200) def test_main_using_main_template(self): client = Client() response = client.get('/main/') self.assertTemplateUsed(response, 'main.html') def test_template_rendering(self): client = Client() response = client.get('/main/') self.assertEqual(response.status_code, 200) # Cek konten template self.assertContains(response, "Welcome to Poké.co") self.assertContains(response, "Player Information") self.assertContains(response, "Featured Character") self.assertContains(response, "Name:") self.assertContains(response, "Class:") # Cek gambar self.assertInHTML("<img alt=\"Pikachu\" src=\"/static/main/assets/Angry-Pikachu-Transparent.png\">", response.content.decode()) # Cek konten footer self.assertContains(response, "Fadhil Muhammad (2206083464). Pemrograman Berbasis Platform Gasal 23/24.")
Lalu, jalankan testing tersebut dengan menjalankan perintah berikut
python manage.py test
-
Melakukan Deployment
Setelah semua tahap selesai, deploy aplikasi ke Adaptable.
Django adalah sebuah framework web yang memungkinkan pengembang untuk dengan mudah membuat dan mengelola situs web yang responsif dan dinamis. Django berfungsi dengan cara berikut:
-
Permintaan dari Client: Ketika seorang pengguna membuka situs web di peramban (browser), peramban akan mengirimkan permintaan HTTP ke server Django.
-
Routing dan URL Pattern: Django memiliki sistem routing yang akan memeriksa pola URL pada permintaan dari client untuk menentukan tindakan atau view apa yang harus diambil untuk menangani permintaan tersebut.
-
Menghubungkan dengan views.py: Setelah pola URL cocok dengan permintaan, Django akan memanggil fungsi yang sesuai dalam berkas views.py. Fungsi-fungsi ini berisi program-program untuk menangani permintaan tersebut.
-
Interaksi dengan models.py: Untuk mengambil atau memanipulasi data yang diperlukan, views.py akan berinteraksi dengan berkas models.py. Models digunakan untuk mendefinisikan struktur data dan hubungan antar data dalam aplikasi.
-
Membangun Halaman Web (HTML): Setelah data yang diperlukan telah diambil dari models.py, views.py akan menggunakan template HTML yang ada dalam direktori templates untuk merender halaman web. Data yang telah diambil dapat dimasukkan ke dalam template untuk membuat halaman web yang dinamis.
-
HTTP Response: Terakhir, views.py akan mengembalikan hasilnya dalam bentuk respons HTTP. Respons ini berisi halaman web yang telah dibuat (dalam bentuk HTML) dan akan dikirimkan kembali kepada client yang mengirimkan permintaan awal.
Ada beberapa alasan mengapa kita sangat disarankan atau diharuskan menggunakan virtual environment saat memulai proyek Django, di antaranya:
-
Dependensi Tertutup
Virtual environment memungkinkan kita untuk membuat lingkungan Python yang terisolasi secara mandiri dari instalasi Python global di sistem. Ini berarti kita dapat memiliki versi Python dan paket dependensi yang berbeda untuk setiap proyek, tanpa khawatir konflik antara versi atau paket yang digunakan oleh proyek yang berbeda.
-
Cleanliness dan Pengelolaan Dependensi
Dengan menggunakan virtual environment, kita dapat mengelola dependensi proyek kita dengan lebih mudah. Kita dapat menginstal modul-modul Python yang diperlukan secara terpisah untuk setiap proyek. Selain itu, kita dapat dengan mudah membuat daftar dependensi proyek (biasanya disimpan dalam berkas
requirements.txt
) untuk mengulangi pengaturan proyek di environment lain atau bagi orang lain yang ingin bekerja pada proyek tersebut. -
Keamanan
Virtual environment dapat membantu mencegah terjadinya masalah jika ada pembaruan atau perubahan yang perlu kita lakukan pada sebuah proyek, tanpa memengaruhi proyek lain yang menggunakan versi Python atau paket yang berbeda.
Pengerjaan proyek Django tanpa menggunakan virtual environment tetap dapat dilaksanakan. Meskipun demikian, poin-poin di atas menjelaskan mengapa virtual environment sangat penting digunakan.
MVC (Model-View-Controller), MVT (Model-View-Template), dan MVVM (Model-View-ViewModel) adalah tiga kerangka arsitektur yang umum digunakan dalam pengembangan perangkat lunak. Tujuan utamanya adalah membagi komponen-komponen inti dalam aplikasi dan mempermudah manajemen kode. Meskipun ketiganya memiliki kesamaan dalam pemisahan peran, terdapat perbedaan signifikan dalam bagaimana mereka mengatur dan berinteraksi antara satu sama lain.
MVC adalah pendekatan yang pertama kali muncul dalam pengembangan perangkat lunak. Dalam MVC, aplikasi dibagi menjadi tiga komponen utama: Model, View, dan Controller. Model bertanggung jawab atas manajemen data dan logika bisnis, View bertanggung jawab untuk menampilkan data kepada pengguna, sementara Controller bertindak sebagai perantara yang mengoordinasikan aliran data dan tindakan yang dilakukan pengguna.
MVT, atau Model-View-Template, adalah varian dari MVC yang sering digunakan dalam kerangka kerja web seperti Django. Dalam MVT, Model tetap mengelola data dan logika bisnis, sedangkan Template mengambil peran View dalam menampilkan data kepada pengguna. Controller pada dasarnya terintegrasi dalam kerangka kerja Django, sehingga pengembang tidak perlu membuatnya secara eksplisit.
Sementara itu, MVVM adalah arsitektur yang lebih modern, sering digunakan dalam pengembangan aplikasi berbasis antarmuka pengguna, seperti aplikasi seluler atau desktop. Dalam MVVM, Model tetap mengelola data dan logika bisnis, tetapi ada tambahan komponen yang disebut ViewModel. ViewModel bertindak sebagai perantara antara Model dan View, mengubah data Model agar sesuai dengan tampilan yang diinginkan oleh View, dan mengelola tindakan yang dilakukan oleh pengguna.
Perbedaan utama antara ketiga pendekatan ini terletak pada cara mereka mengatur peran dan tanggung jawab komponen-komponen utama dalam aplikasi. MVC dan MVT umumnya digunakan dalam konteks aplikasi web tradisional, sementara MVVM lebih sering diterapkan dalam aplikasi modern berbasis antarmuka pengguna. Semua arsitektur ini bertujuan untuk memudahkan pemeliharaan kode, meningkatkan skalabilitas, dan memahami konsep dalam pengembangan perangkat lunak, dengan pilihan tergantung pada jenis aplikasi yang dikembangkan dan preferensi pengembangnya.
Tugas 3
- Langkah-Langkah Pengimplementasian
- Apa perbedaan antara form POST dan form GET dalam Django?
- Apa perbedaan utama antara XML, JSON, dan HTML dalam konteks pengiriman data?
- Mengapa JSON sering digunakan dalam pertukaran data antara aplikasi web modern?
- Postman
File forms.py
dalam proyek Django digunakan untuk mendefinisikan formulir yang akan digunakan dalam aplikasi web. Formulir dapat dihubungkan dengan model Django untuk membuat, mengubah, atau menghapus objek model berdasarkan input dari pengguna.
Isi forms.py
:
from django.forms import ModelForm
from main.models import Item
class ProductForm(ModelForm):
class Meta:
model = Item
fields = ["name", "amount", "rarity", "power", "description"]
Untuk menampilkan jumlah item yang ada pada models, tambahkan kode pada views.py
agar jumlah item pada models dapat diakses.
Update fungsi show_main()
menjadi:
def show_main(request):
total_characters = Item.objects.count() or 0
total_pokemon = Item.objects.aggregate(total_amount=Sum('amount'))['total_amount'] or 0
items = Item.objects.all()
context = {
'name':'Fadhil Muhammad',
'class':'PBP-B',
'char_name':'Pikachu',
'char_description':'Pikachu, the most popular character.',
'char_rarity':'Rare',
'total_characters':total_characters,
'total_pokemon':total_pokemon,
'items':items
}
return render(request, 'main.html', context)
Menambahkan create_item.html
untuk tampilan form yang akan ditampilkan kepada user saat diakses. Untuk ini, django telah menyediakan opsi yang memudahkan kita dalam pembuatan laman formulir.
Isi create_item.html
:
{% extends 'base.html' %}
{% block content %}
<h1>Add New Character to Your List</h1>
<form method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
<tr>
<td></td>
<td>
<input type="submit" value="Add Character"/>
</td>
</tr>
</table>
</form>
{% endblock %}
Buat folder baru pada root directory bernama templates
dan tambahkan file base.html
di dalamnya.
Isi dari base.html
:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
{% block meta %}
{% endblock meta %}
</head>
<body>
{% block content %}
{% endblock content %}
</body>
</html>
Untuk menampilkan data yang telah disubmit pada form, perlu dilakukan penambahan pada main.html
.
Kode yang ditambahkan:
...
...
<section>
<h2>Your Collections</h2>
<p>You currently own a total of {{total_characters}} characters and a total of {{total_pokemon}} Pokémons</p>
<div style="overflow-y: auto;">
<table>
<tr>
<th>Timestamp (UTC+7)</th>
<th>Name</th>
<th>Amount</th>
<th>Rarity</th>
<th>Power</th>
<th>Description</th>
</tr>
{% for item in items %}
<tr>
<td>{{item.date_added}}</td>
<td>{{item.name}}</td>
<td>{{item.amount}}</td>
<td>{{item.rarity}}</td>
<td>{{item.power}}</td>
<td style="min-width: 500px;">{{item.description}}</td>
</tr>
{% endfor %}
</table>
<br />
</div>
<a href="{% url 'main:create_item' %}">
<button>
Add New Character
</button>
</a>
</section>
...
...
Untuk melihat data-data yang disimpan dalam bentuk XML atau JSOn, digunakan serializer. Untuk melihat hasil serializer dari XML atau JSON, tambahkan dua fungsi berikut pada views.py
:
def show_xml(request):
data = Item.objects.all()
return HttpResponse(serializers.serialize("xml", data), content_type="application/xml")
def show_json(request):
data = Item.objects.all()
return HttpResponse(serializers.serialize("json", data), content_type="application/json")
dan tambahkan path berikut pada urls.py
direktori aplikasi:
...
urlpatterns = [
...
path('xml/', show_xml, name='show_xml'),
path('json/', show_json, name='show_json'),
...
]
...
Untuk menampilkan views dari id
masing-masing data, tambahkan fungsi berikut pada views.py
:
def show_xml_by_id(request, id):
data = Item.objects.filter(pk=id)
return HttpResponse(serializers.serialize("xml", data), content_type="application/xml")
def show_json_by_id(request, id):
data = Item.objects.filter(pk=id)
return HttpResponse(serializers.serialize("json", data), content_type="application/json")
dan path berikut pada urls.py
aplikasi:
...
urlpatterns = [
...
path('xml/<int:id>/', show_xml_by_id, name='show_xml_by_id'),
path('json/<int:id>/', show_json_by_id, name='show_json_by_id')
]
...
Dalam Django, form POST dan form GET memiliki beberapa perbedaan utama:
-
Form POST: Form POST dalam Django dikembalikan menggunakan metode POST, di mana browser mengumpulkan data formulir, meng-encode-nya untuk transmisi, mengirimkannya ke server, dan kemudian menerima kembali responsnya1. Metode POST akan mengirimkan data atau nilai langsung ke file lain2. Pemakaian metode POST ini digunakan untuk mengirimkan data yang penting / kredensial dan data yang orang lain tidak boleh tau / secret data, seperti password, dan sebagainya2.
-
Form GET: Sebaliknya, GET mengumpulkan data yang dikirimkan menjadi sebuah string, dan menggunakan ini untuk menyusun URL1. Metode GET akan menampilkan data/nilai pada URL, kemudian akan ditampung oleh action3.
Secara umum, metode POST digunakan saat kita ingin mengirimkan data yang tidak boleh dilihat oleh pengguna lain (misalnya password), sedangkan metode GET digunakan saat kita ingin pengguna dapat melihat data yang dikirimkan (misalnya dalam pencarian).
referensi: Django - Working with forms
XML, JSON, dan HTML adalah tiga format yang sering digunakan dalam pengiriman data di web. Berikut adalah perbedaan utama antara ketiganya:
-
XML (eXtensible Markup Language):
- XML adalah bahasa markup yang menyediakan aturan untuk menentukan data apa pun.
- XML menggunakan tkita untuk membedakan antara atribut data dan data aktual.
- XML merepresentasikan data dalam pola struktur tree.
- XML memisahkan data dari HTML.
- XML menyederhanakan proses perubahan platform.
-
JSON (JavaScript Object Notation):
- JSON adalah format pertukaran data terbuka yang dapat dibaca baik oleh manusia maupun mesin
- JSON bersifat independen dari setiap bahasa pemrograman dan merupakan output API umum dalam berbagai aplikasi
- JSON menggunakan pasangan key-value untuk merepresentasikan data
- JSON mendukung dan didukung semua browser.
-
HTML (HyperText Markup Language):
- HTML adalah bahasa markup stkitar untuk dokumen yang dirancang untuk ditampilkan di browser web. HTML tidak dirancang sebagai format pertukaran data, tetapi sebagai format untuk menampilkan data, dengan fokus pada bagaimana data tampak bagi pengguna akhir.
- HTML menggunakan tag yang dikelilingi oleh tkita kurung sudut (< dan >) untuk membuat elemen.
Dalam konteks pengiriman data, baik XML dan JSON digunakan secara luas. Namun, JSON dianggap lebih efisien karena data direpresentasikan sebagai objek JavaScript, dan dengan demikian beberapa bit dilewatkan melalui kabel. Lebih sedikit waktu mesin diperlukan untuk pemrosesan data.
Singkatnya, JSON adalah format pertukaran data yang lebih baik, sedangkan XML adalah format pertukaran dokumen yang lebih baik. HTML biasanya tidak digunakan untuk pertukaran data, tetapi lebih fokus pada menampilkan data ke pengguna.
HTML
XML
JSON
Tugas 4
Membuat file register.html
yang ada pada direktori main\templates\
untuk menampilkan page ketika user melakukan registrasi akun.
{% extends 'base.html' %}
{% block meta %}
<title>Register</title>
{% endblock meta %}
{% block content %}
<div class = "login">
<h1>Register</h1>
<form method="POST" >
{% csrf_token %}
<table>
{{ form.as_table }}
<tr>
<td></td>
<td><input type="submit" name="submit" value="Daftar"/></td>
</tr>
</table>
</form>
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endblock content %}
Menambahkan fungsi registrasi agar user baru bisa menambahkan akunnya. Menambahkan fungsi berikut ini pada main\views.py
:
def register(request):
form = UserCreationForm()
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Your account has been successfully created!')
return redirect('main:login')
context = {'form':form}
return render(request, 'register.html', context)
Menambahkan login.html
pada direktori main\templates
untuk template yang akan digunakan user saat proses login.
{% extends 'base.html' %}
{% block meta %}
<title>Login</title>
{% endblock meta %}
{% block content %}
<div class = "login">
<h1>Login</h1>
<form method="POST" action="">
{% csrf_token %}
<table>
<tr>
<td>Username: </td>
<td><input type="text" name="username" placeholder="Username" class="form-control"></td>
</tr>
<tr>
<td>Password: </td>
<td><input type="password" name="password" placeholder="Password" class="form-control"></td>
</tr>
<tr>
<td></td>
<td><input class="btn login_btn" type="submit" value="Login"></td>
</tr>
</table>
</form>
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
Don't have an account yet? <a href="{% url 'main:register' %}">Register Now</a>
</div>
{% endblock content %}
Menambahkan fungsi berikut pada views.py
agar data yang ditampilkan adalah data milik user yang berhasil login.
def login_user(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
response = HttpResponseRedirect(reverse("main:show_main"))
response.set_cookie('last_login', str(datetime.datetime.now()))
return response
else:
messages.info(request, 'Sorry, incorrect username or password. Please try again.')
context = {}
return render(request, 'login.html', context)
Untuk menunjukkan kapan user terakhir login, tambahkan potongan kode berikut pada main\templates\main.html
.
...
<h5>Last Login:</h5>
<p>{{ last_login }}</p>
...
Untuk menampilkan item-item yang sesuai dan meminta login user, ubah isi fungsi show_main
pada views.py
dengan kode berikut.
@login_required(login_url='/login')
def show_main(request):
total_characters = Item.objects.filter(user=request.user).count() or 0
total_pokemon = Item.objects.filter(user=request.user).aggregate(total_amount=Sum('amount'))['total_amount'] or 0
items = Item.objects.filter(user=request.user)
context = {
'name':request.user.username,
'class':'PBP-B',
'char_name':'Pikachu',
'char_description':'Pikachu, the most popular character.',
'char_rarity':'Rare',
'total_characters':total_characters,
'total_pokemon':total_pokemon,
'items':items,
'last_login':request.COOKIES['last_login']
}
return render(request, 'main.html', context)
Agar user yang berhasil login dapat keluar, tambahkan button logout dengan menambahkan potongan kode berikut di main.html
pada direktori main\templates
:
...
...
<a href="{% url 'main:logout' %}">
<button>
Logout
</button>
</a>
...
...
Setelah itu, tambahkan fungsi logout pada views.py
:
def logout_user(request):
logout(request)
response = HttpResponseRedirect(reverse('main:login'))
response.delete_cookie('last_login')
return response
Menambahkan potongan kode berikut pada main.html
yang ada pada direktori main\templates
untuk menambahkan tombol menambah dan mengurangi jumlah item serta menghapus item.
...
<a href="{% url 'main:delete_item' item.id %}#item-table">
<button>delete</button>
</a>
....
<a href="{% url 'main:subtract_item' item.id %}#item-{{item.id}}">
<button>-</button>
</a>
....
<a href="{% url 'main:add_item' item.id %}#item-{{item.id}}">
<button>+</button>
</a>
Setelah itu tambahkan fungsi delete_item
, subtract_item
, dan add_item
pada views.py
.
def delete_item(request, item_id):
item = Item.objects.get(pk=item_id)
item.delete()
return redirect('main:show_main')
def add_item(request, item_id):
item = Item.objects.get(pk=item_id)
item.amount += 1
item.save()
return redirect('main:show_main')
def subtract_item(request, item_id):
item = Item.objects.get(pk=item_id)
item.amount = max(0, item.amount - 1)
item.save()
return redirect('main:show_main')
UserCreationForm
adalah salah satu dari built-in forms yang disediakan oleh Django untuk mengelola proses otentikasi pengguna. Form ini dirancang khusus untuk membuat pengguna baru (user registration). Dengan menggunakan UserCreationForm
, kita dapat dengan mudah membuat halaman pendaftaran pengguna dalam aplikasi Django. Form ini secara otomatis meng-handle validasi, penyimpanan data pengguna, dan proses pembuatan akun. Kelebihan dari UserCreationForm
adalah menyediakan proses pembuatan akun yang terstkitardisasi dan sesuai dengan praktik keamanan yang baik. Kelemahannya adalah kemungkinan perlu disesuaikan untuk memenuhi kebutuhan khusus aplikasi.
-
Autentikasi adalah proses verifikasi identitas pengguna, yaitu memastikan bahwa pengguna adalah benar-benar pemilik akunnya. Dalam konteks Django, hal ini berarti memeriksa apakah pengguna memiliki akun yang valid dan telah memasukkan kredensial yang benar (seperti username dan password).
-
Otorisasi adalah proses menentukan akses apa yang diberikan kepada pengguna setelah pengguna berhasil diotentikasi. Hal Ini melibatkan kontrol terhadap hak akses pengguna terhadap sumber daya atau tindakan tertentu dalam aplikasi, seperti apakah pengguna memiliki izin untuk melihat halaman tertentu atau melakukan tindakan tertentu.
Apa itu cookies dalam konteks aplikasi web, dan bagaimana Django menggunakan cookies untuk mengelola data sesi pengguna?
Cookies adalah data kecil yang disimpan oleh browser web pada komputer user. Cookies digunakan oleh situs web untuk menyimpan informasi tertentu pada laman web user, yang kemudian dapat digunakan untuk mengenali user ketika mereka kembali ke situs tersebut. Dalam konteks aplikasi web, cookies sering digunakan untuk mengelola sesi user, menyimpan preferensi, data, atau melacak perilaku user.
Django menggunakan cookies untuk mengelola data sesi pengguna. Ini berarti Django dapat menyimpan informasi sesi, seperti data login atau preferensi pengguna, di dalam cookies. Hal ini memungkinkan pengguna untuk tetap terotentikasi di seluruh sesi tanpa harus terus-menerus melakukan login kembali.
Apakah penggunaan cookies aman secara default dalam pengembangan web, atau apakah ada risiko potensial yang harus diwaspadai?
Penggunaan cookies dalam pengembangan web akan aman jika diterapkan dengan benar. Namun, ada beberapa risiko potensial yang perlu diwaspadai, termasuk:
- Cross-Site Scripting (XSS): Serangan yang memungkinkan penyerang menyisipkan kode skrip berbahaya ke dalam cookies pengguna.
- Cross-Site Request Forgery (CSRF): Serangan yang memungkinkan penyerang menjalankan tindakan tertentu atas nama pengguna tanpa persetujuan mereka.
- Session Hijacking: Potensi pencurian cookies sesi yang dapat digunakan oleh penyerang untuk mengakses akun pengguna.
Cookies dapat dengan mudah diakses oleh pengguna melalui web, sehingga tidak cocok untuk menyimpan informasi yang sensitif.
Tugas 5
Pada tugas ini, saya membuat desain web dengan menggunakan CSS untuk mempercantik tampilan laman web yang sudah saya buat sebelumnya.
Saya membuat file CSS untuk setiap laman web yang saya buat. File CSS berisi aturan-aturan untuk mengatur gaya tampilan elemen-elemen HTML yang ada pada laman web. Saya menambahkan atribut class atau id pada tag HTML yang ingin saya beri gaya. Kemudian, saya menggunakan selector yang sesuai untuk menentukan elemen mana yang akan diberi gaya pada file CSS.
Berikut adalah file CSS yang saya buat untuk setiap laman web:
- create_item.css: File ini berisi gaya untuk laman web yang digunakan untuk membuat item baru. Saya mengatur warna latar belakang, font, margin, padding, border, dan lain-lain untuk elemen-elemen seperti form, input, button, dan label.
- login.css: File ini berisi gaya untuk laman web yang digunakan untuk login. Saya mengatur warna latar belakang, font, margin, padding, border, dan lain-lain untuk elemen-elemen seperti form, input, button, dan label.
- main.css: File ini berisi gaya untuk laman web utama yang menampilkan daftar item yang tersedia. Saya mengatur warna latar belakang, font, margin, padding, border, dan lain-lain untuk elemen-elemen seperti div, h1, h2, ul, li, a, dan img.
- register.css: File ini berisi gaya untuk laman web yang digunakan untuk registrasi. Saya mengatur warna latar belakang, font, margin, padding, border, dan lain-lain untuk elemen-elemen seperti form, input, button, dan label.
Saya juga menambahkan beberapa gambar dari internet untuk membuat laman web menjadi lebih menarik.
Dalam CSS, ada tiga jenis selector utama: element selector, class selector, dan id selector.
-
Element Selector: Selector ini digunakan untuk memilih elemen HTML berdasarkan nama elemennya. Misalnya, jika ingin menerapkan gaya yang sama ke semua elemen
<p>
di halaman web, kita dapat menggunakan element selector. Manfaatnya adalah dapat mengubah gaya semua elemen dengan jenis tertentu sekaligus. -
Class Selector: Selector ini digunakan untuk memilih elemen berdasarkan class-nya. Class selector sangat berguna ketika kita ingin menerapkan gaya yang sama ke sekelompok elemen tanpa memkitang jenis elemennya. kita dapat menggunakan class selector ketika kita memiliki beberapa elemen yang ingin diberi gaya yang sama.
-
ID Selector: Selector ini digunakan untuk memilih satu elemen unik berdasarkan id-nya. ID selector biasanya digunakan ketika kita ingin menerapkan gaya khusus ke satu elemen saja di halaman web kita. Perlu diingat bahwa setiap id harus unik dan hanya dapat digunakan sekali dalam satu halaman.
Pemilihan selector yang tepat tergantung pada kebutuhan dan struktur halaman web kita. Jika kita ingin menerapkan gaya yang sama ke banyak elemen, gunakan class selector. Jika kita ingin menerapkan gaya khusus ke satu elemen saja, gunakan id selector. Dan jika kita ingin mengubah gaya semua elemen dengan jenis tertentu, gunakan element selector.
HTML5 memperkenalkan sejumlah tag baru yang memberikan lebih banyak fleksibilitas dan interaktivitas dalam mendesain halaman web. Berikut adalah beberapa tag HTML5 yang saya ketahui:
-
<!DOCTYPE html>
: Tag ini digunakan untuk mendeklarasikan tipe dokumen dan versi HTML, dalam hal ini HTML5. -
<header>
: Tag ini digunakan untuk merangkum konten pengantar atau navigasi. Biasanya berisi judul situs, logo, dan menu navigasi. -
<nav>
: Tag ini digunakan untuk merangkum bagian navigasi situs web, biasanya berisi daftar tautan menu. -
<main>
: Tag ini digunakan untuk konten utama dari halaman web yang unik dan tidak termasuk dalam konten yang diulang di seluruh situs web seperti header, footer, atau navigasi. -
<article>
: Tag ini digunakan untuk merangkum konten mandiri yang dapat dipahami secara independen dari konten lainnya, seperti postingan blog atau berita. -
<section>
: Tag ini digunakan untuk mengelompokkan konten terkait dalam suatu bagian dokumen. -
<aside>
: Tag ini digunakan untuk konten yang sedikit terkait dengan konten utama sekitarnya, seperti sidebar atau iklan. -
<footer>
: Tag ini digunakan untuk merangkum informasi penutup seperti informasi hak cipta, tautan ke kebijakan privasi, dll. -
<figure>
dan<figcaption>
: Tag ini digunakan untuk merangkum gambar, diagram, foto, kode, dll., dan judul atau keterangan yang terkait. -
<video>
,<audio>
, dan<source>
: Tag ini digunakan untuk menyematkan media seperti video dan audio ke dalam halaman web. -
<img>
: Tag ini digunakan untuk menyematkan gambar ke dalam halaman web. -
<div>
: Tag ini umumnya digunakan sebagai container.
Margin dan padding adalah dua properti dalam CSS yang digunakan untuk mengendalikan ruang di sekitar elemen. Berikut adalah perbedaan antara keduanya:
-
Margin: Merupakan ruang di luar batas elemen. Margin tidak mempengaruhi ukuran elemen itu sendiri, tetapi menciptakan ruang ekstra di sekitarnya. Margin sering digunakan untuk membuat ruang antara elemen yang berbeda atau antara elemen dengan tepi browser.
-
Padding: Merupakan ruang di dalam batas elemen, antara batas dan konten elemen itu sendiri. Padding mempengaruhi ukuran elemen dan sering digunakan untuk memberikan ruang ekstra di dalam elemen, seperti membuat teks tidak menempel langsung ke batas elemen.
Margin dan padding tidak mempengaruhi ukuran konten elemen itu sendiri, hanya ruang di sekitar kontennya. Juga, keduanya transparan, jadi warna latar belakang elemen atau halaman akan terlihat.
Jelaskan perbedaan antara framework CSS Tailwind dan Bootstrap. Kapan sebaiknya kita menggunakan Bootstrap daripada Tailwind, dan sebaliknya?
Bootstrap memberikan komponen-komponen yang siap digunakan tanpa perlu kita ubah sedangkan tailwind memberikan template-template yang lebih sederhana yang harus kita kustomisasi terlebih dahulu sebelum digunakan. Jadi perbedaannya adalah tailwind lebih fleksibel dalam hal kustomisasi namun kurang cepat dalam hal implementasi sedangkan bootstrap lebih cepat dalam hal implementasi namun kurang fleksibel dalam hal kustomisasi.
Kita bisa menggunakan tailwind ketika kita harus membuat website dengan desain yang rumit dengan waktu yang cukup panjang. Sedangkan kita bisa menggunakan bootstrap ketika kita harus membuat website dengan desain yang sederhana dengan waktu yang singkat.
Tugas 6
Untuk mengubah bagian data cards agar dapat mendukung AJAX, tambahkan kode berikut pada views.py
.
def get_product_json(request):
product_item = Item.objects.filter(user=request.user)
return HttpResponse(serializers.serialize('json', product_item))
Lalu, tambahkan bagian script
pada main.html
pada direktori aplikasi main untuk melakukan pengambilan data dengan kode ini.
async function getItems() {
return fetch("{% url 'main:get_product_json' %}").then((res) => res.json())
}
Untuk melakukan rendering template dari data yang diambil menggunakan AJAX, ubah konfigurasi html di file main.html
, lalu tambahkan kode berikut pada bagian script pada main.html
.
async function refreshProducts() {
document.getElementById("item_cards").innerHTML = ""
const Items = await getItems()
let total_characters = Items.length
let total_pokemon = 0
Items.forEach((item) => {
total_pokemon += item.fields.amount
})
let htmlString = `\n
<h2>Your Collections</h2>
<p id="qty-text">You currently own a total of ${total_characters} characters and a total of ${total_pokemon} Pokémons</p>
<div style="display: flex; flex-wrap: wrap;" id="collection_cards">\n
`
Items.forEach((item) => {
let deleteItemURL = `{% url 'main:delete_item' 0 %}`.replace("0", item.pk)
let addItemURL = `{% url 'main:add_item' 0 %}`.replace("0", item.pk)
let subtractItemURL = `{% url 'main:subtract_item' 0 %}`.replace("0", item.pk)
htmlString += `\n
<div class="card" id="item-${item.pk}">
<div class="card-header">
<a>
<button id="button_delete" data-item-pk=${item.pk}>delete</button>
</a>
</div>
<div class="card-body">
<div class="card-title">${item.fields.name}</div>
<div class="card-info">
<p>Date Added (UTC+7): ${item.fields.date_added}</p><br>
<p>Amount: ${item.fields.amount}</p><br>
<p>Rarity: ${item.fields.rarity}</p><br>
<p>Power: ${item.fields.power}</p><br>
</div>
<div class="card-description">${item.fields.description}</div>
</div>
<div class="card-footer">
<a>
<button id="modify-qty" data-modifier="increment" data-item-pk=${item.pk}>+</button>
</a>
<p style="display: inline-block; margin: 0 10px;">${item.fields.amount}</p>
<a>
<button id="modify-qty" data-modifier="decrement" data-item-pk=${item.pk}>-</button>
</a>
</div>
</div>`;
})
htmlString += `\n
</div>
<a href="{% url 'main:create_item' %}">
<button>
Add New Character
</button>
</a>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
Add New Character by AJAX
</button>
`
document.getElementById("item_cards").innerHTML = htmlString
document.querySelectorAll('#button_delete').forEach(function(button) {
button.addEventListener('click', function() {
let itemPK = this.getAttribute('data-item-pk');
deleteProduct(itemPK);
});
});
document.querySelectorAll("#modify-qty").forEach(function(button) {
button.addEventListener('click', function() {
let itemPK = this.getAttribute("data-item-pk")
let modifier = this.getAttribute("data-modifier")
updateProductQty(itemPK, modifier)
})
})
let x = document.querySelectorAll(".card")
x[x.length - 1].style = "background-color: black; color: white;"
x = document.querySelectorAll(".card-header")
x[x.length - 1].style = "background-color: red;"
x = document.querySelectorAll(".card-footer")
x[x.length - 1].style = "background-color: orange; color: black; border: 1px solid black"
}
Setelah itu, lakukan pemanggilan funcition refreshProducts
agar konten web ter-render dengan benar.
Pertama-tama, menambahkan html ini pada main.html
yang ada pada direktori main/templates
sebagai modal yang digunakan untuk menambahkan item.
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Add New Character</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="form" onsubmit="return false;">
{% csrf_token %}
<div class="mb-3">
<label for="name" class="col-form-label">Name:</label>
<input type="text" class="form-control" id="name" name="name"></input>
</div>
<div class="mb-3">
<label for="amount" class="col-form-label">Amount:</label>
<input type="number" class="form-control" id="amount" name="amount"></input>
</div>
<div class="mb-3">
<label for="rarity" class="col-form-label">Rarity:</label>
<select class="form-select" id="rarity" name="rarity">
<option value="Unknown">Unknown</option>
<option value="Common">Common</option>
<option value="Rare">Rare</option>
<option value="Epic">Epic</option>
<option value="Legendary">Legendary</option>
</select>
</div>
<div class="mb-3">
<label for="power" class="col-form-label">Power:</label>
<input type="number" class="form-control" id="power" name="power"></input>
</div>
<div class="mb-3">
<label for="description" class="col-form-label">Description:</label>
<textarea class="form-control" id="description" name="description"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="button_add" data-bs-dismiss="modal">Add Character</button>
</div>
</div>
</div>
</div>
Selanjutnya, tambahkan kode berikut pada views.py
yang ada pada direktori main
.
@csrf_exempt
def add_product_ajax(request):
if request.method == 'POST':
name = request.POST.get("name")
amount = request.POST.get("amount")
rarity = request.POST.get("rarity")
power = request.POST.get("power")
description = request.POST.get("description")
user = request.user
new_product = Item(name=name,
amount=amount,
rarity=rarity,
power=power,
description=description,
user=user)
new_product.save()
return HttpResponse(b"CREATED", status=201)
return HttpResponseNotFound()
Tidak lupa untuk mengimpor csfr_exempt dari django.
Selanjutnya, tambahkan dan hubungkan path create-product-ajax
pada urlpatterns yang ada di urls.py
. Setelah itu tambahkan kode berikut pada script di main.html
.
function addProduct() {
fetch("{% url 'main:add_product_ajax' %}", {
method: "POST",
body: new FormData(document.querySelector('#form'))
}).then(refreshProducts)
document.getElementById("form").reset()
return false
}
Jalankan
python manage.py collectstatic
Asynchronous programming dan synchronous programming adalah dua pendekatan yang berbeda dalam pengembangan perangkat lunak. Dalam synchronous programming, tugas dieksekusi secara berurutan, satu per satu, yang dapat membuat program terasa lambat jika ada tugas yang memakan waktu lama. Sebaliknya, asynchronous programming memungkinkan eksekusi tugas-tugas berlanjut tanpa harus menunggu tugas sebelumnya selesai. Ini berguna untuk menjaga responsivitas aplikasi dan mengatasi operasi yang memakan waktu. Meskipun synchronous programming lebih mudah dipahami, asynchronous programming merupakan kunci dalam mengatasi tugas kompleks dan menjadikan aplikasi lebih efisien.
Dalam penerapan JavaScript dan AJAX, terdapat penerapan paradigma event-driven programming. Jelaskan maksud dari paradigma tersebut dan sebutkan salah satu contoh penerapannya pada tugas ini.
Paradigma event-driven programming adalah sebuah pendekatan dalam pemrograman yang didasarkan pada konsep penggerak acara atau "events". Dalam paradigma ini, program merespons acara atau kejadian tertentu yang terjadi secara asinkron, seperti interaksi pengguna dengan aplikasi, input dari perangkat luar, atau perubahan status sistem. Ketika suatu acara terjadi, program akan menjalankan fungsi atau prosedur tertentu yang telah ditetapkan sebelumnya sebagai respons terhadap acara tersebut.
Salah satu contoh penerapan pada tugas ini adalah ketika user memencet tombol "add", "subtract", "delete", ataupun ketika user ingin menambahkan item.
document.getElementById("button_add").onclick = addProduct
AJAX, singkatan dari Asynchronous Javascript and XML, adalah teknik pengembangan web yang memungkinkan aplikasi web untuk bekerja secara asynchronous. Dalam konteks ini, asynchronous berarti bahwa AJAX dapat memproses setiap request (permintaan) yang datang ke server di sisi background.
Beberapa penerapan asynchronous programming pada AJAX meliputi pertukaran data, yang memungkinkan pengiriman dan penerimaan data dari server tanpa harus me-reload keseluruhan halaman. Ini berarti bahwa AJAX memungkinkan Asynchronous Calls ke server web sehingga peramban klien tidak perlu menunggu semua data. Selain itu, interaksi pengguna dengan AJAX memungkinkan pembaruan antarmuka pengguna sesuai kebutuhan sepotong demi sepotong, tanpa harus mengisi ulang keseluruhan halaman. Hal ini berkontribusi pada performa dan kecepatan yang lebih baik, karena postback halaman dihilangkan, sehingga aplikasi yang menggunakan AJAX akan lebih responsif, cepat, dan ramah pengguna.
Contoh penggunaan AJAX yang populer adalah fitur Google Autocomplete, yang memberikan saran kata kunci secara real-time ketika pengguna mengetik. Melalui asynchronous programming, AJAX menjadi kunci dalam menciptakan aplikasi web yang responsif dan efisien.
Pada PBP kali ini, penerapan AJAX dilakukan dengan menggunakan Fetch API daripada library jQuery. Bandingkanlah kedua teknologi tersebut dan tuliskan pendapat kamu teknologi manakah yang lebih baik untuk digunakan.
Dalam penggunaan AJAX, terdapat dua teknologi utama yang digunakan, yaitu Fetch API dan library jQuery. Fetch API adalah bagian dari standar JavaScript modern yang diperkenalkan dengan ES6, sedangkan jQuery adalah library JavaScript yang telah ada sejak lama dan memiliki fitur-fitur untuk memudahkan penggunaan AJAX. Namun, ada beberapa perbandingan yang dapat membantu menentukan teknologi mana yang lebih baik digunakan.
Pertama, Fetch API adalah teknologi bawaan yang terdapat dalam semua peramban modern, sehingga tidak memerlukan pengunduhan tambahan seperti jQuery. Ini berarti aplikasi web akan memiliki ukuran yang lebih kecil jika menggunakan Fetch API, yang dapat memengaruhi waktu muat halaman dan efisiensi. Selain itu, Fetch API lebih modern dan mendukung promise, yang mempermudah pengelolaan permintaan asinkron dan menangani respons dari server.
Di sisi lain, jQuery, meskipun merupakan library yang cukup kuat dan telah digunakan selama bertahun-tahun, menjadi kurang relevan dalam lingkungan pengembangan web saat ini karena ukurannya yang besar dan banyak fitur yang mungkin tidak digunakan. Penggunaan jQuery juga dapat memperlambat waktu muat halaman, terutama jika hanya digunakan untuk melakukan permintaan AJAX sederhana.
Dengan pertimbangan ini, Fetch API lebih baik dalam pengembangan web modern karena lebih ringan, lebih efisien, dan memanfaatkan fitur terbaru dari JavaScript. Namun, keputusan akhir tergantung pada proyek dan preferensi pribadi. Jika kita perlu berinteraksi dengan API secara luas atau merasa nyaman dengan penggunaan jQuery, itu mungkin masih menjadi pilihan yang sah. Namun, dalam banyak kasus, Fetch API adalah pilihan yang lebih baik untuk pengembangan web yang lebih efisien dan responsif.