Tutorial CRUD dengan Django dan Boostrap 4 #4: Menambah dan Mengubah Data ke Database


Tutorial CRUD dengan Django dan Boostrap 4 #4: Menambah dan Mengubah Data ke Database

Tambah Task

Pada halaman Tambah Task, kita akan membuat sebuah form dari class Form yang ada pada Django. Tetapi sebelumnya kita perlu menambahkan satu package pada virtual environment. Buka terminal/command prompt dan tambahkan package django-widget-tweaks dengan perintah berikut.

pip install django-widget-tweaks

Kemudian buka file todo-project/app/settings.py dan tambahkan package tersebut dibagian INSTALLED_APPS.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Aplikasi Todo
    'todo.apps.TodoConfig',
    # package untuk merender form pada template
    'widget_tweaks',
]

Django mempunyai fitur untuk membuat objek untuk sebuah form yang mana di dalamnya kita bisa mendefinisikan field-field apa saja yang nantinya ada pada form tersebut. Kita juga bisa menambahkan validasi, mengubah teks label dan pesan errornya untuk setiap validasinya dan merelasikannya dengan Model yang ada. Jadi nantinya form yang kita buat lebih terstruktur.

Oke sekarang langsung saja kita masuk ke kode lagi. Kita buat dulu file baru dengan nama forms.py di dalam folder todo-project/todo. Dan tuliskan kode berikut.

todo-project/todo/forms.py

from django.forms import ModelForm
from django.utils.translation import gettext_lazy as _

# import class Task dari file todo/models.py
from .models import Task


# membuat class TaskForm untuk membuat task
class TaskForm(ModelForm):
    class Meta:
        # merelasikan form dengan model
        model = Task
        # mengeset field apa saja yang akan ditampilkan pada form
        fields = ('title', 'description', 'status')
        # mengatur teks label untuk setiap field
        labels = {
            'title': _('Judul'),
            'description': _('Deskripsi'),
            'status': _('Status')
        }
        # mengatur teks pesan error untuk setiap validasi fieldnya
        error_messages = {
            'title': {
                'required': _("Judul harus diisi."),
            },
            'description': {
                'required': _("Deskripsi harus diisi."),
            },
        }

Setelah itu kita perlu membuat method pada file todo-project/todo/views.py untuk menampilkan halaman tambah task dan juga memroses jika form di submit. buka file tersebut dan lakukan perubahan seperti di bawah ini.

todo-project/todo/views.py

from django.shortcuts import redirect, render
from django.http import Http404
from django.contrib import messages

# import class Task dari file todo/models.py
from .models import Task
# import class TaskForm dari file todo/forms.py
from .forms import TaskForm


# Membuat View untuk halaman daftar task
def index_view(request):
    # Mengambil semua data task
    tasks = Task.objects.all()
    context = {
        'tasks': tasks
    }
    # parsing data task ke template todo/index.html dan merender nya
    return render(request, 'todo/index.html', context)


# Membuat View untuk halaman detail task
def detail_view(request, task_id):
    # Mengambil data task berdasarkan task ID
    try:
        task = Task.objects.get(pk=task_id)
        context = {
            'task': task
        }
    except Task.DoesNotExist:
        # Jika data task tidak ditemukan,
        # maka akan di redirect ke halaman 404 (Page not found).
        raise Http404("Task tidak ditemukan.")
    # parsing data task ke template todo/detail.html dan merendernya
    return render(request, 'todo/detail.html', context)


# Membuat View untuk halaman form tambah task
def create_view(request):
    # Mengecek method pada request
    # Jika method-nya adalah POST, maka akan dijalankan
    # proses validasi dan penyimpanan data
    if request.method == 'POST':
        # membuat objek dari class TaskForm
        form = TaskForm(request.POST)
        # Mengecek validasi form
        if form.is_valid():
            # Membuat Task baru dengan data yang disubmit
            new_task = TaskForm(request.POST)
            # Simpan data ke dalam table tasks
            new_task.save()
            # mengeset pesan sukses dan redirect ke halaman daftar task
            messages.success(request, 'Sukses Menambah Task baru.')
            return redirect('todo:index')
    # Jika method-nya bukan POST
    else:
        # membuat objek dari class TaskForm
        form = TaskForm()
    # merender template form dengan memparsing data form
    return render(request, 'todo/form.html', {'form': form})

Pada kode di atas kita menambahkan kode untuk mengimport class TaskForm

from .forms import TaskForm

Dan kita membuat sebuah method baru yang diberi nama create_view.

def create_view(request):
    # Mengecek method pada request
    # Jika method-nya adalah POST, maka akan dijalankan
    # proses validasi dan penyimpanan data
    if request.method == 'POST':
        # membuat objek dari class TaskForm
        new_task = TaskForm(request.POST)
        # Mengecek validasi form
        if new_task.is_valid():
            # Simpan data ke dalam table tasks
            new_task.save()
            # mengeset pesan sukses dan redirect ke halaman daftar task
            messages.success(request, 'Sukses Menambah Task baru.')
            return redirect('todo:index')
    # Jika method-nya bukan POST
    else:
        # membuat objek dari class TaskForm
        form = TaskForm()
        # merender template form dengan memparsing data form
        return render(request, 'todo/form.html', {'form': form})

Tahap selanjutnya tentu kita perlu mengubah pada template form nya, Buka file todo-project/todo/templates/todo/form.html dan ubah menjadi seperti di bawah ini.

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <title>Todo App</title>

    <style>
      body {
        margin-top: 30px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1>Task Form</h1>

      <div>
        <a href="{% url 'todo:index' %}" class="btn btn-success">Back to List</a>
      </div>

      <br>

      <div>
        <!-- meload package untuk merender form field -->
        {% load widget_tweaks %}

        <form method="post" novalidate>
          <!-- menambahkan csrf field untuk keamanan form -->
          {% csrf_token %}

          <!-- merender semua field form dari objek TaskForm -->
          {% if form.non_field_errors %}
            <div class="alert alert-danger" role="alert">
              {% for error in form.non_field_errors %}
                {{ error }}
              {% endfor %}
            </div>
          {% endif %}

          {% for field in form.visible_fields %}
            <div class="form-group">
              {{ field.label_tag }}

              {% if form.is_bound %}
                {% if field.errors %}
                  {% render_field field class="form-control is-invalid" %}
                  {% for error in field.errors %}
                    <div class="invalid-feedback">
                      {{ error }}
                    </div>
                  {% endfor %}
                {% else %}
                  {% render_field field class="form-control is-valid" %}
                {% endif %}
              {% else %}
                {% render_field field class="form-control" %}
              {% endif %}

              {% if field.help_text %}
                <small class="form-text text-muted">{{ field.help_text }}</small>
              {% endif %}
            </div>
          {% endfor %}

          <button type="submit" class="btn btn-primary">Submit</button>
        </form>
      </div>
  </div>
 
  </body>
</html>

Nah pada file template todo-project/todo/templates/todo/index.html, kita perlu mengubah url pada tombol Tambah Baru dan menambahkan kode blok untuk menampilkan pesan sukses ketika berhasil menambahkan task. Ubah bagian kode blok untuk tombol Tambah Baru.

<div>
	<a href="#" class="btn btn-success">Tambah Baru</a>
</div>

Menjadi seperti berikut ini.

<!-- blok untuk menampilkan notifikasi pesan sukses -->
<div>
{% if messages %}

  	{% for message in messages %}
  	<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
    	<button type="button" class="close" data-dismiss="alert" aria-label="Close">
      		<span aria-hidden="true">&times;</span>
    	</button>
      	{{ message | safe }}
  	</div>
  	{% endfor %}

{% endif %}
</div>

<!-- tombol untuk ke halaman tambah task -->
<div>
	<a href="{% url 'todo:create'  %}" class="btn btn-success">Tambah Baru</a>
</div>

Terakhir tambahkan route baru untuk halaman tambah task pada file todo-project/todo/urls.py seperti di bawah ini.

todo-project/todo/urls.py

from django.urls import path

# import View dari todo Application
from .views import index_view, detail_view, create_view

app_name = 'todo'
urlpatterns = [
	# url untuk halaman daftar task
    path('', index_view, name='index'),
    # url untuk halaman detail task
    path('<int:task_id>', detail_view, name='detail'),
    # url untuk halaman tambah task
    path('create', create_view, name='create')
]

Jalankan kembali aplikasi kita dan buka halaman daftar task dari url http://127.0.0.1:8000/todo dan klik tombol Tambah Baru maka aplikasi akan membuka halaman tambah task seperti di bawah ini.

Jika kamu tidak mengisi form nya, maka ketika klik tombol submit, server akan mengembalikan pesan error dari validasi formnya dan meredirect tetap pada halaman tambah task. Pada template kita sudah menambahkan kode juga untuk menampilkan pesan error tiap field atau kolomnya seperti di bawah ini.

Coba isi form dengan benar dan klik tombol submit, maka server akan mengeset notifikasi pesan sukses dan mengarahkan kita kembali ke halaman daftar task. Pada template kita juga sudah menambahkan kode untuk menampilkan pesan sukses dari server.

Ubah Task

Untuk halaman ubah task kita akan menggunakan template dan Form yang sama. sehingga kita hanya butuh untuk menambahkan method di View untuk menangani proses update data dan menambahan juga route baru untuk halaman ubah task. Tambahkan kode berikut pada file todo-project/todo/views.py.

# Membuat View untuk halaman form ubah task
def update_view(request, task_id):
    try:
        # mengambil data task yang akan diubah berdasarkan task id
        task = Task.objects.get(pk=task_id)
    except Task.DoesNotExist:
        # Jika data task tidak ditemukan,
        # maka akan di redirect ke halaman 404 (Page not found).
        raise Http404("Task tidak ditemukan.")
    # Mengecek method pada request
    # Jika method-nya adalah POST, maka akan dijalankan
    # proses validasi dan penyimpanan data
    if request.method == 'POST':
        form = TaskForm(request.POST, instance=task)
        if form.is_valid():
            # Simpan perubahan data ke dalam table tasks
            form.save()
            # mengeset pesan sukses dan redirect ke halaman daftar task
            messages.success(request, 'Sukses Mengubah Task.')
            return redirect('todo:index')
    # Jika method-nya bukan POST
    else:
        # membuat objek dari class TaskForm
        form = TaskForm(instance=task)
    # merender template form dengan memparsing data form
    return render(request, 'todo/form.html', {'form': form})

Kemudian untuk menambahkan route, kita perlu mengubah file todo-project/todo/urls.py menjadi seperti ini.

from django.urls import path

# import View dari todo Application
from .views import index_view, detail_view, create_view, update_view

app_name = 'todo'
urlpatterns = [
    # url untuk halaman daftar task
    path('', index_view, name='index'),
    # url untuk halaman detail task
    path('<int:task_id>', detail_view, name='detail'),
    # url untuk halaman tambah task
    path('create', create_view, name='create'),
    # url untuk halaman ubah task
    path('update/<int:task_id>', update_view, name='update'),
]

Terakhir kita perlu menambahkan url halaman ubah task pada tombol ubah di halaman daftar task. Cari bagian kode berikut.

<a href="#" class="btn btn-primary btn-sm">ubah</a>

Dan ubah menjadi seperti kode di bawah ini.

<a href="{% url 'todo:update' task.id %}" class="btn btn-primary btn-sm">ubah</a>

Sekarang pilih salah satu baris pada tabel daftar task dan klik tombol ubah. maka kita akan diarahkan ke halaman ubah task, yang mana tampilannya sama dengan halaman tambah task, hanya saja setiap isian form sudah terisi dengan data task yang akan kita ubah. Coba kita ubah datanya kemudian klik tombol submit.

Maka server akan memroses perubahan data dan mengarahkan kita kembali ke halaman daftar task beserta menampilkan notifikasi pesan sukses sama seperti pada proses penambahan task.


INFO : Ebook Python & Django


Rizqi Maulana
Backend Developer

Suka dengan tulisan di SantriKoding? Kamu bisa memberikan dukungan dengan berdonasi atau bagikan konten ini di sosial media. Terima kasih atas dukungan Anda!

KEBIJAKAN KOMENTAR

Saat memberikan komenatar silahkan memberikan informasi lengkap tentang error, seperti: screenshot, link kode, dll. Baca aturan komentar kami