Membangun Aplikasi Mini HRD dengan Django (2): Membuat Autentikasi Sederhana dan Mengenal Views

Ridwan Fajar 5 Juni 2016

Membangun Aplikasi Mini HRD dengan Django (2): Membuat Autentikasi Sederhana dan Mengenal Views

Saat berada di tutorial "Pengenalan Django Admin", kita sudah menyelesaikan empat fitur dengan menggunakan django admin. Anda dapat melihat bagaimana django admin dapat membantu Anda untuk membuat sebuah produk minimal dari target yang Anda kejar. Mungkin saja Anda memutuskan untuk hanya menggunakan django admin karena merasa sudah terpenuhi spesifikasi yang dibutuhkannya.

Namun tidak semua hal dapat diselesaikan dengan django admin, misalnya Anda ingin melihat sebuah grafikyang memperlihatkan performa kehadiran seorang karyawan perbulan, atau mencetak daftar kehadiran dalam format PDF, tentu saja kita harus membuat sendiri halaman tersebut dengan perangkat untuk membuat halaman web pada umumnya.

Di tutorial sebelumnya hanya user yang sebagai staff dan admin saja yang dapat mengakses halaman django admin. User yang hanya memiliki status active tidak dapat mengakses halaman django admin. Oleh karena itu, di tutorial ini kita akan mencoba membuat sebuah halaman khusus untuk karyawan yang ingin melihat daftar kehadiranya. Selain itu karyawan tersebut dapat melihat profil dirinya yang telah dicatat oleh admin.

Membuat modul homepage

Untuk memenuhi quest kita di tutorial ini, kita akan membuat sebuah modul baru yang bernama homepage. Modul tersebut akan berisi penanganan login dan logout dan mungkin nantinya Anda dapat mengisinya oleh halaman - halaman seperti contact, about, home, dan informasi lainnya yang bersifat publik. Seperti biasa kita akan menggunakan perintah startapp untuk membuat modul homepage:
$python manage.py startapp homepage
Jangan lupa, setiap modul yang telah kita buat, harus didaftarkan ke settings.py bila ingin modul tersebut disertakan dalam aplikasi. Silahkan tambahkan homepage di bawah kehadiran dan karyawan:
........................

DEBUG = True

ALLOWED_HOSTS = []

Application definition

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'kehadiran', 'karyawan', 'homepage', ]

........................

Membuat login dan logout di modul homepage

Setiap function yang akan menangani sebuah proses request harus disimpan di file views.py di suatu modul. Sekarang kita akan membuat proses login dan logout di dalam homepage/views.py. Silahkan telaah dan salin kode dibawah ini:
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, logout, login
from django.contrib import messages

from karyawan.models import Akun, Karyawan

Create your views here.

def login_view(request): if request.POST: user = authenticate(username=request.POST['username'], password=request.POST['password']) if user is not None: if user.is_active: try: akun = Akun.objects.get(akun=user.id) login(request, user)

                request.session['karyawan_id'] = akun.karyawan.id
                request.session['jenis_akun'] = akun.jenis_akun
                request.session['username'] = request.POST['username']
            except:
                messages.add_message(request, messages.INFO, 'Akun ini belum terhubung dengan data karyawan, silahkan hubungi administrator')
            return redirect('/')
        else:   
            messages.add_message(request, messages.INFO, 'User belum terverifikasi')
    else:
        messages.add_message(request, messages.INFO, 'Username atau password Anda salah')

return render(request, 'login.html')

def logout_view(request): logout(request) return redirect('/login/')

Pada proses import modul python diatas, kita meng-import modul django seperti untuk keperluan flash message, autentikasi, template rendering, dan redirect halaman. Kita akan menggunakan render dan redirect yang disediakan oleh Django Shortcuts di dalam function tertentu di file views.py. Function render digunakan untuk memproses sebuah file template menjadi teks berupa HTML. Anda pun dapat melewatkan sebuah nilai kedalamnya misal sebuah daftar karyawan atau daftar kehadiran dalam bentuk list python dilewatkan agar bisa ditampilkan dalam bentuk tabel. Sedangkan function redirect digunakan untuk mengalihkan halaman web yang sedang diakses ke halaman lain. Misal ketika Anda berhasil login maka Anda akan dialihkan ke halaman profil terlebih dahulu sebelum menjelajah halaman lain.

Kemudian kita pun menggunakan function authenticate, logout, dan login yang disediakan oleh Django Contrib Auth di function login_view dan logout_view. Secara teknis, authenticate akan memeriksa identitas yang dikirimkan dari form login untuk diperiksa keberadaannya di tabel User. Bila tidak ada maka proses login akan gagal. Sedangkan function login bertugas untuk memanipulasi objek request dengan mencatatkan session yang akan kita atur untuk proses autentikasi. Function logout akan menghapus session dan objek user dari request. Dan terakhir kita menggunakan messages yang disediakan Django Contrib untuk mengirimkan flash message sebagai notifikasi bila terjadi kegagalan proses login. Anda pun dapat menggunakan messages untuk menampilkan hasil validasi form.

Sekarang mari kita mulai telusuri function login_view dan logout_view. Sebelum itu kita harus terlebih dahulu menyertakan model Akun dan Karyawan dari karyawan/models.py untuk mengambil identitas karyawan yang akan login dan menyimpannya di session. Sebuah function yang akan digunakan untuk menangani request di Django, harus selalu menerima sebuah variabel yang akan menerima objek request. Parameter setelahnya dapat bervariasi sesuai dengan keinginan. Di dalam function login_view terdapat sebuah proses pengecekan apakah request yang datang adalah POST atau bukan. Bila bukan POST maka akan ditampilkan langsung halaman login yang berisi form login.

Bila POST maka akan masuk ke proses selanjutnya yaitu proses autentikasi user. Jika user tidak terdaftar maka akan akan ditampilkan halaman login dengan pesan "Username atau password Anda salah". Bila user terdaftar maka akan masuk ke proses berikutnya yaitu pengecekan apakah user merupakan user aktif atau bukan. Bila user belum diaktifkan maka akan tampil halaman login dengan pesan "User belum terverifikasi", bila user sudah aktif maka akan terjadi proses pencatatan session dengan mengambil data Karyawan yang terhubung ke akun yang akan diakses. Tapi kita pun menggunakan try..catch untuk menangani error apabila akun yang digunakan belum terhubung ke karyawan manapun. Jika berhasil maka user akan dialihkan ke halaman utama.

Di proses logout kita hanya melakukan pembersihan request dari session dan menghilangkan objek user yang sudah tercatat sewaktu login. Dengan demikian ketika kita akan mengakses view yang sudah dibentengin dengan proses pemeriksaan login akan tidak dapat diakses dan akan dialihkan ke form login. Karena kita membutuhkan sebuah file template yang bernama login.html, Anda harus membuat sebuah folder bernama templates di dalam folder homepage terlebih dahulu. Setelah itu barulah Anda membuat file login.html yang akan kita isi dengan source code dibawah ini:

<!DOCTYPE html>
<htmL>
    <head>
        <title>Mini HRD</title>
    </head>
    <body>
        <h1>Silahkan Login</h1>
        <form action="/login/" method="POST">
            {% csrf_token %}

            {% if messages %}
              <ul>
                {% for message in messages %}
                  <li>{{ message }}</li>
                {% endfor %}
              </ul>
            {% endif %}

            <p>Username: <input type="text" name="username" value="" placeholder="silahkan masukkan username..." /></p>
            <p>Password: <input type="password" name="password" value="" placeholder="silahkan masukkan password..." /></p>
            <p><input type="submit" value="Log In" /></p>
        </form>
    </body>
</htmL>

Pada form diatas kita melewatkan sebuah perintah penting yaitu "{% csrf_token %}". Perintah csrf_token harus digunakan bila kita mengaktifkan pemeriksaan CSRF. Suatu form akan selalu diberi penanda apakah form tersebut berasal dari website kita atau bukan. Di dalam django template, tag {% ... %} digunakan untuk melakukan pemanggilan fungsi atau melakukan suatu operasi misalnya looping, atau pemeriksaan kondisi berupa if .. else. sedangkan tag {{ ... }} digunakan untuk mencetak sebuah variabel yang dilewatkan ke halaman atau saat melakukan looping.

Kita mengirimkan dua buah nilai yaitu username dan password ke URL "/login/" dengan method POST. Setelah dikirim maka proses login yang sebelumnya telah dijelaskan akan dieksekusi dan berlanjut ke penampilan profil karyawan.

Membuat halaman profil karyawan

Setelah selesai membuat views untuk login dan logout, kini kita akan membuat sebuah views yang dibentengi dengan sebuah decorator Python untuk melakukkan proses autentikasi terlebih dahulu. Decorator adalah sebuah function yang akan dieksekusi terlebih dahulu sebelum function yang akang digunakan diproses. Kita akan menggunakan sebuah decorator yang disediakan oleh Django Contrib Auth yaitu login_required. Decorator login_required memerlukan sebuah parameter yaitu URL yang akan digunakan untuk mengarahkan kita ke halaman login. Maka dari itu kita tambahkan sebuah variabel di settings.py yaitu LOGIN_URL agar dapat digunakan ulang di setiap function yang menggunakan decorator login_required.
.............................

Static files (CSS, JavaScript, Images)

https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'

LOGIN_URL = '/login/'

.............................

Setelah itu kita lanjutkan dengan membuat sebuah function yang bernama profil dan kita bentengi function tersebut dengan decorator login_required. Di dalam function tersebut kita melakukan query dengan menggunakan Django ORM (object relational mapper). Kita mengambil sebuah data karyawan dengan menggunakan function get() berdasarkan id dari karyawan tersebut. Ada cukup banyak function yang dapat digunakan untuk melakukan query menggunakan Django ORM. Ada all(), get(), filter(), exclude(), dan lainnya. Anda dapat melihatnya di dokumentasi resmi Django. Setelah mengambil data karyawan yang terkait dengan akun yang berhasil login, kita melakukan rendering template profil.html dengan melewatkan data karyawan ke dalam template tersebut. Silahkan salin kode dibawah ini ke karyawan/views.py:

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.conf import settings

from karyawan.models import Karyawan
# Create your views here.

@login_required(login_url=settings.LOGIN_URL)
def profil(request):
    karyawan = Karyawan.objects.get(id=request.session['karyawan_id'])
    return render(request, 'profil.html', {"karyawan":karyawan})

Perlu Anda perhatikan, sintaks Karyawan.objects.get(id=request.session['karyawan_id']) dapat diartikan sebagai "SELECT * FROM karyawan WHERE id='10'".

Sama halnya dengan membuat template untuk homepage, Anda harus membuat terlebih dahulu sebuah folder bernama templates di dalam modul karyawan, barulah setelah itu membuat file template dengan nama profil.html. Di dalam file profil.html tersebut Anda akan mengurasi setiap field dari objek karyawan yang telah berhasil login. Silahkan salin kode dibawahini ke karyawan/templates/profil.html:

<!DOCTYPE html>
<htmL>
    <head>
        <title>Mini HRD</title>
    </head>
    <body>
        <h1>Silahkan Login</h1>
        <form>
            <h1>Profil Anda ({{ request.session.jenis_akun }})</h1>
            <p>Hi, {{ request.session.username }}</p>
            <p>Nama: {{ karyawan.nama }}</p>
            <p>Alamat: {{ karyawan.alamat }}</p>
            <p>Jenis Kelamin: {{ karyawan.jenis_kelamin }}</p>
            <p>Jenis Karyawan: {{ karyawan.jenis_karyawan }}</p>
            <p>No Telepon: {{ karyawan.no_telepon }}</p>
            <p>Email: {{ karyawan.email }}</p>
            <p>No Rekening: {{ karyawan.no_rekening }}</p>
            <p>Pemilik Rekening: {{ karyawan.pemilik_rekening }}</p>
            <p>Divisi: {{ karyawan.divisi.nama }}</p>
            <p>Jabatan: {{ karyawan.jabatan.nama }}</p>
            <p><a href="/logout/">Log out</a> | <a href="/daftar_hadir/">Kehadiran</a></p>
        </form>
    </body>
</htmL>

Dan terakhir, kita harus menambatkan function - function yang ada di views yang telah dipaparkan sebelumnya ke mini_hrd/urls.py. Di dalam file urls.py kita akan menentukan URL dan function apa yang akan menanganinya. Kita akan mendaftarkan URL root atau "/" ke views karyawan_views.profil, kemudian URL "/daftar_hadir/" pun didaftarkan ke kehadiran_views.daftar_hadir yang akan kita kerjakan di bagian selanjutnya. Sedangkan login dan logout dapat Anda lihat pada source code dibawah ini:

from django.conf.urls import url
from django.contrib import admin

from homepage import views as homepage_views
from karyawan import views as karyawan_views
from kehadiran import views as kehadiran_views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', karyawan_views.profil),
    url(r'^login/', homepage_views.login_view),
    url(r'^logout/', homepage_views.logout_view),
    url(r'^daftar_hadir/', kehadiran_views.daftar_hadir),
]

Setelah semua selesai ditelaah dan disalin, sekarang kita akan menjalankan kembali aplikasi mini hrd ini dengan perintah pamungkas berikut:

$ python manage.py runserver

Sekarang mari kita lihat beberapa screenshot dari hasil pekerjaan yang telah kita lakukan:

Selection_001 Selection_002 Selection_003

Menampilkan daftar hadir dalam bentuk tabel

Untuk menampilkan daftar hadir, kita memerlukan sebuah data kehadiran seorang karyawan tentunya. Anda dapat melakukan query pada tabel Kehadiran dengan melakukan filter berdasarkan tahun dan bulan yang diinginkan. Tentu saja Anda harus mengisinya dahulu melalui django admin sebelum mencoba tutorial ini. Anda dapat mengisi data sample Anda sendiri, misal mengisi data kehadiran seorang karyawan di bulan mei 2016 selama 21 hari kerja: Selection_004

Sekarang mari kita membuat sebuah views daftar_hadir di kehadiran/views.py. Function tersebut akan kita bentengin dengan decorator login_required. Kemudian di dalamnya terdapat pengecekan apabila request adalah POST maka lakukan proses query untuk mengambil data kehadiran suatu karyawan pada bulan tertentu dan bulan tertentu. Setelah itu kita akan menampilkan halaman daftar hadir dengan data kehadiran yang telah diambil. Bila tidak ada data kehadiran pada bulan yang diinginkan, maka akan diberi peringatan bahwa data kehadiran pada waktu tersebut tidak ada.

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.conf import settings

from karyawan.models import Karyawan
from kehadiran.models import Kehadiran

# Create your views here.

@login_required(login_url=settings.LOGIN_URL)
def daftar_hadir(request):
    daftar_hadir = None

    if request.method == 'POST':
        bulan = request.POST['bulan']
        tahun = request.POST['tahun']
        daftar_hadir = Kehadiran.objects.filter(waktu__year=tahun, waktu__month=bulan, karyawan__id=request.session['karyawan_id'])

    return render(request, 'daftar_hadir.html', {'daftar_hadir':daftar_hadir})

Perlu Anda perhatikan, sintaks Kehadiran.objects.filter(waktu__year=tahun, waktu__month=bulan, karyawan__id=request.session['karyawan_id']) dapat diartikan sebagai "SELECT * FROM kehadiran WHERE YEAR(kehadiran.waktu) ='2016 AND MONTH(kehadiran.waktu)='05' AND kehadiran.karyawan_id='10'".

Sekarang seperti biasa, silahkan buat template daftar_hadir.html di kehadiran/templates. Setelah itu silahkan salin kode dibawahini:

<!DOCTYPE html>
<htmL>
    <head>
        <title>Mini HRD</title>
    </head>
    <body>
        <h1>Daftar Hadir</h1>
        <form action='/daftar_hadir/' method="POST">
            {% csrf_token %}
            <select name="tahun">
                <option value="2016">2016</option>
                <option value="2015">2015</option>
                <option value="2014">2014</option>
            </select>
            <select name="bulan">
                <option value="01">Januari</option>
                <option value="02">Februari</option>
                <option value="03">Maret</option>
                <option value="04">April</option>
                <option value="05">Mei</option>
                <option value="06">Juni</option>
                <option value="07">Juli</option>
                <option value="08">Agustus</option>
                <option value="09">September</option>
                <option value="10">Oktober</option>
                <option value="11">November</option>
                <option value="12">Desember</option>
            </select>
            <input type="submit" value="Tampilkan" />
        </form>
        <br/>
        <table border="1">
            <thead>
                <tr>
                    <td>No</td>
                    <td>Tanggal</td>
                    <td>Status</td>
                </tr>
            </thead>
            <tbody>
                {% if daftar_hadir %}
                    {% for hadir in daftar_hadir %}
                    <tr>
                        <td>{{ forloop.counter }}</td>
                        <td>{{ hadir.waktu }}</td>
                        <td>{{ hadir.jenis_kehadiran }}</td>
                    </tr>
                    {% endfor %}
                {% else %}
                <tr>
                    <td colspan="3">Tidak ada data kehadiran saat ini...</td>
                </tr>
                {% endif %}
            </tbody>
        </table>
        <p><a href="/">Kembali ke Profil</a></p>
    </body>
</htmL>

Ada sebuah sintaks yang cukup unik, yaitu {{ forloop.counter }}. Sintaks tersebut digunakan untuk mengambil berada di iterasi keberapakah pengulangan yang sedang dilakukan. Hal ini berguna untuk menampilkan penomoran pada baris suatu tabel. Sekarang mari kita lihat hasil pekerjaan kita melalui screenshot berikut:

Selection_005 Selection_006

Penutup

Di tutorial ini, Anda sudah mencoba beberapa hal seperti membuat autentikasi sederhana, melakukan query dengan Django ORM, menampilkan halaman HTML dengan Django Template, membuat views dan mendaftarkannya ke urls.py, serta mempelajari beberapa fitur Django seperti decorator dan shortcut. Di tutorial berikutnya, Anda akan membuat sebuah form yang dihasilkan oleh Django sesuai dengan model yang kita definisikan. Di dalam tutorial ini, kita masih membuat form secara manual.

(rfs/djangoproject)