---
title: "Perkenalan ke tampilan berdasarkan-kelas"
version: 2.1
locale: id
source: https://docs.djangoproject.com/id/2.1/topics/class-based-views/intro/
canonical: https://djangodocs.dev/id/2.1/topics/class-based-views/intro/
---
# Perkenalan ke tampilan berdasarkan-kelas

Tampilan berdasarkan-kelas menyediakan cara alternatif untuk menerapkan tampilan sebagai obyek Python daripada fungsi. Mereka tidak mengganti tampilan berdasarkan-fungsi, tetapi mempunyai perbedaan dan keuntungan tertentu ketika dibandingkan pada tampilan berdasarkan-fungsi:

- Kode organisasi terkait pada metode HTTP tertentu (`GET`, `POST`, dll.) dapat dialamatkan oleh metode terpisah sebagai gantinya dari percabangan bersyarat.
- Teknik-teknik berorientasi obyek seperti mixin (banyak warisan) dapat digunakan pada kode faktor kedalam komponen digunakan kembali.

## Hubungan dan riwayat dari tampilan umum, tampilan berdasarkan-kelas, dan tampilan umum berdasarkan-kelas

Dalam permulaan ada hanya kontrak fungsi tampilan, Django melewatkan fungsi anda sebuah [`HttpRequest`](/id/2.1/ref/request-response/#django.http.HttpRequest) dan berharap kembali sebuah [`HttpResponse`](/id/2.1/ref/request-response/#django.http.HttpResponse). Ini adalah perpanjangan dari apa Django sediakan.

Lebih awal pada itu telah dikenali dimana ada dialek umum dan pola ditemukan di pengembangan tampilan. Tampilan umum berdasarkan-fungsi telah diperkenalkan untuk meringkas pola ini dan pengembangan tampilan mudah untuk kasus-kasus umum.

Masalah dengan tampilan umum berdasarkan-fungsi adalah bahwa selagi mereka mencangkupi kasus-kasus kecil juga, tidak ada cara memperpanjang atau menyesuaikan mereka diluar beberapa pilihan konfigurasi sederhana, membatasi kegunaan mereka di banyak aplikasi dunia-sebenarnya.

Tampilan umum berdasarkan-kelas telah dibuat dengan tujuan sama sebagai tampilan umum berdasarkan-fungsi, untuk membuat tampilan pengembangan lebih mudah. Bagaimanapun, cara pemecahan diterapkan, melalui penggunaan dari mixin, menyediakan sebuah alat bantu yang menghasilkan di tampilan umum berdasarkan-kelas menjadi lebih diperpanjang dan lentur daripada pasangan berdasarkan-fungsi mereka.

Jika anda telah mencoba tampilan umum berdasarkan fungsi di waktu lampau dan menemukan kekurangan mereka, anda tidak harus memikirkan tampilan umum berdasarkan-kelas sebagai setara berdasarkan-kelas sederhana, melainkan sebagai pendekatan segar untuk mengatasi masalah asli yang tampilan umum dimaksud untuk memecahkan.

Alat bantu dari kelas-kelas dasar dan mixin yang Django gunakan untuk membangun tampilan umum berdsarkan-kelas dibangun untuk kemudahan maksimal, dan dengan demikian mempunyai banyak kaitan di formulir dari penerapan metode awalan dan atribut dimana yang tidak mungkin bersangkutan dengan penggunaan kasus termudah. Sebagai contoh, daripada membatasi anda pada atribut berdasarkan-kelas untuk `form_class`, penerapan menggunakan metode `get_form`, yang memanggil metode `get_form_class`, yang di penerapan awalannya hanya mengembalikan atribut `form_class` dari kelas. Ini memberikan anda beberapa pilihan untuk menentukan formulir apa yang digunakan, dari atribut sederhana, ke sepenuhnya dinamis, kaitan callable . Pilihan ini terlihat menambahkan lubang kerumitan untuk keadaan sederhana, tetapi tanpa mereka, rancangan lebih lanjut akan menjadi terbatas.

## Menggunakan tampilan berdasarkan-kelas

Pada intinya, tampilan berdasarkan-kelas mengizinkan anda menanggapi ke permintaan HTTP berbeda dengan metode instance kelas berbeda, daripada dengan kode cabang bersyarat didalam fungsi tampilan tunggal.

Jadi dimana kode untuk menangani HTTP `GET` di sebuah fungsi tampilan akan terlihat seperti:

```
from django.http import HttpResponse

def my_view(request):
    if request.method == 'GET':
        # <view logic>
        return HttpResponse('result')
```

Di tampilan berdasarkan-kelas, ini akan menjadi:

```
from django.http import HttpResponse
from django.views import View

class MyView(View):
    def get(self, request):
        # <view logic>
        return HttpResponse('result')
```

Karena penyelesai URL Django berharap mengirim permintaan dan argumen terkait ke fungsi callable, bukan kelas, tampilan berdasarkan-kelas mempunyai sebuah metode kelas [`as_view()`](/id/2.1/ref/class-based-views/base/#django.views.generic.base.View.as_view) yang mengembalikan fungsi yang dapat dipanggil ketika permintaan tiba untuk URL mencocokkan corak terkait. Fungsi membuat sebuah instance dari kelas dan memanggil metode meth:~django.views.generic.base.View.dispatch nya. Tampilan 11dispatch\`\` pada permintaan menentukan apakah itu adalah `GET`, `POST`, dll, dan menyampaikan permintaan pada metode pencocokan jika satu ditentukan, atau muncul [`HttpResponseNotAllowed`](/id/2.1/ref/request-response/#django.http.HttpResponseNotAllowed) jika tidak:

```
# urls.py
from django.urls import path
from myapp.views import MyView

urlpatterns = [
    path('about/', MyView.as_view()),
]
```

Itu perlu dicatat bahwa apa metode anda kembalikan mirip ke apa anda kembalikan dari tampilan berdasarkan-fungsi, yaitu beberapa formulir dari [`HttpResponse`](/id/2.1/ref/request-response/#django.http.HttpResponse). Ini berarti bahwa obyek [http shortcuts](/id/2.1/topics/http/shortcuts/) atau [`TemplateResponse`](/id/2.1/ref/template-response/#django.template.response.TemplateResponse) sah digunakan didalam tampilan berdasarkan-kelas.

Selagi tampilan berdasarkan-kelas paling rendah tidak membutuhkan atribut kelas apapun untuk melakukan pekerjaannya, atribut kelas berguna di banyak perancangan berdasarkan-kelas, dan ada dua cara mengkonfigurasi atau mensetel atribut kelas.

Pertama adalah cara Python standar dari mensubkelaskan dan menimpa atribut dan metode di subkelas. Sehingga jika induk anda mempunyai sebuah atribut `greeting` seperti ini:

```
from django.http import HttpResponse
from django.views import View

class GreetingView(View):
    greeting = "Good Day"

    def get(self, request):
        return HttpResponse(self.greeting)
```

Anda dapat menimpa itu di subkelas:

```
class MorningGreetingView(GreetingView):
    greeting = "Morning to ya"
```

Pilihan lain adalah mengkonfigurasi atribut kelas sebagai argumen kata kunci pada panggailan [`as_view()`](/id/2.1/ref/class-based-views/base/#django.views.generic.base.View.as_view) di URLconf:

```
urlpatterns = [
    path('about/', GreetingView.as_view(greeting="G'day")),
]
```

> **Note**
>
> Selagi kelas anda diinstasiasikan untuk setiap permintaan dikirimkan ke itu, atribut kelas menyetel melalui titik masukan [`as_view()`](/id/2.1/ref/class-based-views/base/#django.views.generic.base.View.as_view) dikonfigurasikan hanya sekali pada waktu URL anda diimpor.

## Menggunakan mixin

Mixin adalah sebuah formulit dari banyak warisan dimana perilaku dan atribut dari banyak kelas-kelas induk dapat dipadukan

Sebagai contoh, di tampilan berdasarkan-kelas umum adalah sebuah mixin dipanggil [`TemplateResponseMixin`](/id/2.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin) yang tujuan utamanya adalah menentukan metode [`render_to_response()`](/id/2.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response). Ketika memadukan dengan perilaku dari kelas dasar [`View`](/id/2.1/ref/class-based-views/base/#django.views.generic.base.View), hasil adalah kelas [`TemplateView`](/id/2.1/ref/class-based-views/base/#django.views.generic.base.TemplateView) yang akan mengirim permintaan ke metode pencocokan sesuai (sebuah perilaku ditentukan di kelas dasar `View`), dan itu mempunyai sebuah metode [`render_to_response()`](/id/2.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response) yang menggunakan sebuah atribut [`template_name`](/id/2.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.template_name) untuk mengembalikan sebuah obyek [`TemplateResponse`](/id/2.1/ref/template-response/#django.template.response.TemplateResponse) (sebuah perilaku ditentukan di `TemplateResponseMixin`).

Mixin adalah sebuah cara istimewa dari menggunakan kembali kode terhadap banyak kelas, tetapi mereka datang dengan beberapa biaya. Semakin kode anda tersebar diantara mixin, semakin keras itu akan dibaca kelas anak dan mengetahui apa yang sebenarnya itu lakukan, dan semakin keras itu akan diketahui metode mana dari mixin mana untuk ditimpa jika anda mensubkelaskan sesuatu yang mempunyai pohon warisan dalam.

Catat juga bahwa anda dapat hanya mewarisi dari satu tampilan umum - yaitu, hanya satu kelas induk mungkin mewarisi dari [`View`](/id/2.1/ref/class-based-views/base/#django.views.generic.base.View) dan sisa (jika ada) harus berupa mixin. Mencoba mewarisi lebih dari satu kelas yang mewarisi dari `View` \- sebagai contoh, mencoba menggunakan sebuah formulir pada atas dari daftar dan memadukan [`ProcessFormView`](/id/2.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.ProcessFormView) dan [`ListView`](/id/2.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView) \- tidak bekerja sesuai harapan.

## Menangani formulir dengan tampilan berdasarkan-kelas

Sebuah dasar tampilan berdasarkan-fungsi yang menangani formulir mungkin terlihat sesuatu seperti ini:

```
from django.http import HttpResponseRedirect
from django.shortcuts import render

from .forms import MyForm

def myview(request):
    if request.method == "POST":
        form = MyForm(request.POST)
        if form.is_valid():
            # <process form cleaned data>
            return HttpResponseRedirect('/success/')
    else:
        form = MyForm(initial={'key': 'value'})

    return render(request, 'form_template.html', {'form': form})
```

Tampilan berdasarkan-kelas yang mirip mungkin terlihat seperti:

```
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views import View

from .forms import MyForm

class MyFormView(View):
    form_class = MyForm
    initial = {'key': 'value'}
    template_name = 'form_template.html'

    def get(self, request, *args, **kwargs):
        form = self.form_class(initial=self.initial)
        return render(request, self.template_name, {'form': form})

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if form.is_valid():
            # <process form cleaned data>
            return HttpResponseRedirect('/success/')

        return render(request, self.template_name, {'form': form})
```

Ini adalah kasus sangat mudah, tetapi anda dapat melihat bahwa anda akan kemudian memiliki pilihan dari penyesuaian tampilan ini dengan menimpa setiap dari atribut kelas, sebagai contoh `form_class`, melalui konfigurasi URLconf, atau mensubkelaskan dan menimpa satu atau lebih metode (atau keduanya!).

## Menghias tampilan berdasarkan-kelas

Tambahan dari tampilan berdasarkan-kelas tidak terbatas menggunakan mixin. Anda dapat juga menggunakan penghias. Sejak tampilan berdasarkan-kelas bukan fungsi, mengias mereka bekerja secara berbeda tergantung pada jika anda sedang menggunakan `as_view()` atau membuat sebuah subkelas.

### Menghias URLconf

Cara termudah dari menghias tampilan berdasarkan-kelas adalah menghias hasil dari metode [`as_view()`](/id/2.1/ref/class-based-views/base/#django.views.generic.base.View.as_view). Tempat termudah untuk melakukan ini adalah di URLconf dimana anda menyebarkan tampilan anda:

```
from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView

from .views import VoteView

urlpatterns = [
    path('about/', login_required(TemplateView.as_view(template_name="secret.html"))),
    path('vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]
```

Pendekatan ini memberlakukan penghias pada dasar per-instance. Jika anda ingin setiap instance dari tampilan dihias, anda butuh mengambil pendekatan berbeda.

### Menghias kelas

Untuk menghias setiap instance dari tampilan berdasarkan-kelas, anda butuh menghias pengertian kelas itu sendiri. Untuk melakukan ini anda berlakukan penghias ke metode [`dispatch()`](/id/2.1/ref/class-based-views/base/#django.views.generic.base.View.dispatch) dari kelas.

Sebuah metode pada sebuah kelas tidak agak sama seperti fungsi berdiri sendiri, jadi anda tidak hanya memberlakukan penghias fungsi ke metode -- anda butuh merubah itu menjadi penghias metode dahulu. Penghias `method_decorator` merubah sebuah penghias  fungsi kedalam penghias metode sehingga itu dapat digunakan pada metode instance. Sebagai contoh:

```
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

class ProtectedView(TemplateView):
    template_name = 'secret.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)
```

Atau, lebih ringkas, anda dapat menghias kelas dan melewatkan nama dari metode untuk di hias sebagai argumen kata kunci `name`:

```
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'
```

Jika anda mempunyai sekumpulan penghias umum digunakan di beberapa tempat, anda dapat menentukan daftar atau tuple dari penghias dan menggunakan ini sebagai gantinya meminta `method_decorator()` berulang kali. Kedua kelas ini adalah setara:

```
decorators = [never_cache, login_required]

@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

@method_decorator(never_cache, name='dispatch')
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'
```

Penghias akan mengolah sebuah permintaan dalam urutan mereka dilewatkan ke penghias. Dalam contoh, `never_cache()` akan mengolah permintaan sebelum `login_required()`.

Di contoh ini, setiap instance dari `ProtectedView` akan mempunyai perlindungan masuk.

> **Note**
>
> `method_decorator` melewatkan `*args` dan `**kwargs` sebagai parameter untuk menghiasi metode pada kelas. Jika metode anda tidak menerima sekumpulan cocok dari parameter itu akan memunculkan sebuah pengecualian `TypeError`.
