Catatan Belajar Django PART 3: Templates

Saat membuat website pada umumnya selain sistem yang berjalan diperlukan juga tampilan untuk user interfacenya. Di Django ini jadi tanggung jawab templates. Pada dasarnya django secara default memasang templates di direcotry app, jadi struktur app nya seperti berikut

├── admin.py
├── apps.py
├── forms.py
├── __init__.py
├── migrations
├── models.py
├── templates
│   └── index.html
├── tests.py
├── urls.py
└── views.py

Tapi beberapa orang (termasuk saya) lebih menyukai dibuat sentralisasi untuk templates, apalagi kalau konteknya emang 1 projek keseluruhan, mungkin jika membuat module lebih baik di app, tapi kalau kesatuan projek saya lebih suka dengan sentralisasi

Untuk sentralisasi template saya pernah menulisnya di tulisan berikut [link] tulisan di bawah ini berfokus kepada penggunaan template.

Saya sendiri menggunakan yang sentralisasi templates.

Render

Jika di tulisan sebelumnya hasil dari views langsung dimunculkan sebagai http response, di tulisan ini memperlihatkan bagaiman dari views masuk ke template, buka kode yang kemarin lalu ubah menjadi seperti berikut:

from django.http import HttpResponse
from django.shortcuts import render  #tambahkan ini
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods


@csrf_exempt
@require_http_methods(["GET", "POST"])
def hello_world(request):
    if request.method == "GET":
        return render(request, "index.html") #dari httpresponse menjadi render
    else:
        return HttpResponse("Insert Hello world")

Lalu isi index.html seperti berikut

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    Halo from template
</body>
</html>

Sehingga saat akes url tujuan menampilkan sebagai berikut

Halo from template

Passing parameter & Django Template Engine

Hanya menampilkan html tentu tidak berguna karena akan sulit untuk mendapatkan nilai dinamis, untuk menampilkan tampilan dinamis kita bisa mengirimkan nilai dari views ke template dan nanti akan dimunculan dengan django template

Ubah views menjadi seperti berikut:

def hello_world(request):
    if request.method == "GET":
        context = {"hello": "hello from views"} #siapkan dictionary
        return render(request, "index.html", context) #masukan dictionary sebagai parameter tambahan
    else:
        return HttpResponse("Insert Hello world")

dan templates menjadi

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    {{ hello }}
</body>
</html>

Maka saat diakses akan memunculkan “hello from views”.

Untuk print out variable yang dikirimkan menggunakan double kurung kurawan buka `{{` dan double kurung kurawal tutup `}}`

Django template juga tidak hanya untuk printout, untuk proses seperti looping dan conditional juga bisa

Conditional & Looping

Tambahkan dulu kode views menjadi seperti berikut

def hello_world(request):
    if request.method == "GET":
        context = {
            "hello": "hello from views",
            "groups": ["SHP", "Heart", "Kid"],
            "age": 25,
        }
        return render(request, "index.html", context)
    else:
        return HttpResponse("Insert Hello world")

dan template seperti ini

# conditional
 <hr>
    {% if age > 25 %}
        Dewasa
    {% elif age >= 17 and age < 24 %}
        Remaja
    {% else %}
        Anak-anak

    {% endif %}
# looping
<hr>
    Loop:
    <hr>
    <ul>
    {% for g in groups %}
       <li> {{ g }}</li>
    {% endfor %}
    </ul>

Perintah di atas akan memunculkan list yang ditampilkan dengan tag `<li>`
Kalau diperhatikan ada yang berbeda
untuk printout : `{{ }}`
untuk “fungsi”: `{% %}`

Link and url name

Salah satu yang paling sering digunakan di website adalah link, dan link ini digunakan dari mulai tombol sampai dengan form, basic html seperti berikut

<a href="http://localhost:8000/front/2">ke menu 2</a>

Itu akan menuju ke halaman yang dituju, tapi gak enak kalau harus nulis lengkap, dan dan bisa saja suatu hari nanti alamat webnya bisa berubah asalanya `front/2` jadi `depan/2` misalnya. Akan ribet mengganti target href satu persatu, di sini kita bisa menggunakan name di url

Buka dulu `blog/urls.py` dan ubah sebagai berikut

urlpatterns = [
    path("", views.hello_world, name="home"),
    path("<str:name>", views.hello_segment, name="detail-home"),
]

lalu di template kita bisa gunakan

<a href="{% url "home" %}">ke Depan</a>
#ini akan menghasilkan http://localhost:8000/front/
    
<a href="{% url "detail-home" 2 %}">ke Detail</a>
#ini akan meghasilkan http://localhost:8000/front/2

URL Namespace

Di contoh di atas hanya ada app blog, di banyak projek django terdiri banyak app, dan bisa saja di app itu name url nya bisa sama, misal home disitulah fungsinya namespace

ubah `blog/urls.py`

app_name = "blog"
urlpatterns = [
    path("", views.hello_world, name="home"),
    path("<str:name>", views.hello_segment, name="detail-home"),
]

Lalu cara manggilnya

<a href="{% url "blog:home" %}">ke Depan</a>
 <a href="{% url "blog:detail-home" 2 %}">ke Detail</a>

Layout, Page, dan Komponen

Sebenarnya itu istilah favorit saya sih, seringkali saya ketika membuat struktur folder template selalu menerapkan 3 folder tersebut

Layout: Untuk base template, misal layout login, layout dashboard, layout front end
Pages: Untuk lokasi halaman yang ditentukan, biasanya ini menempel ke layout tertentu
Komponen: Lebih bebas, misal bisa saja kita punya komponen table, bisa saja table yang sama kita munculkan baik di dashboard atau di frontend

Mari buat contoh sederhana

Saya akan buat 2 layout (layouts/first.html, layouts/second.html) dan dua halaman yang terikat ke masing-masing layout (pages/page_first.html, pages/page_second.html) dan satu komponen list (components/list.html) yang muncul di dua halaman tadi

struktur templates

├── components
│   └── list.html
├── index.html
├── layouts
│   ├── first.html
│   └── second.html
└── pages
    ├── page_first.html
    └── page_second.html

Ada dua layout

Layout satu: layout/first.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=<device-width>, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Ini Layout nomor 1</h1>

    {% block content %}{% endblock %}
</body>
</html>


Layout dua: layout/second.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=<device-width>, initial-scale=1.0">
    <title>Document</title>
</head>
<body style="background: blue;">
    <h1>Ini Layout nomor 2</h1>

    {% block content %}{% endblock %}
</body>
</html>

Untuk page

pages/page_first
```html
{% extends 'layouts/first.html' %}

{% block content %}
{% include "components/list.html" with data=categories %}
{% endblock %}

```

pages/page_second
```html
{% extends 'layouts/second.html' %}

{% block content %}
{% include "components/list.html" with data=categories %}
{% endblock %}
```

Komponen

component/list
```html

<ul>
{% for d in data %}
    <li> {{ d.name }}</li>
{% endfor %}
</ul>

Dan urls

urls

from django.urls import path

from . import views

app_name = "blog"
urlpatterns = [
    path("layout", views.layout_satu, name="layout"),
    path("layout2", views.layout_dua, name="layout2"),
]

views

def layout_satu(request):
    categories = Category.objects.all()
    context = {"categories": categories}
    return render(request, "pages/page_first.html", context)


def layout_dua(request):
    categories = Category.objects.all()
    context = {"categories": categories}
    return render(request, "pages/page_second.html", context)

hasilnya

Jika diperhatikan di atas ada 3 template tag yang berperan penting:

extends: untuk menentukan layout yang digunakan
blocks: untuk menandakan lokasi render
includes: untuk memasukan halaman

Tulisan terkait template sepertinya cukup sampai sini, terima kasih.