---
title: "Tampilan umum berdasarkan kelas siap-pakai"
version: 5.1
locale: id
source: https://docs.djangoproject.com/id/5.1/topics/class-based-views/generic-display/
canonical: https://djangodocs.dev/id/5.1/topics/class-based-views/generic-display/
---
# Tampilan umum berdasarkan kelas siap-pakai

Writing web applications can be monotonous, because we repeat certain patterns
again and again. Django tries to take away some of that monotony at the model
and template layers, but web developers also experience this boredom at the view
level.

*tampilan umum* Django dikembangkan untuk memudahkan sakit itu. Mereka mengambil dialek umum tertentu dan pola ditemukan di pengembangan tampilan dan meringkaskan mereka sehingga anda dapat dengan cepat menulis tampilan umum dari data tanpa harus menulis  kode terlalu banyak.

Kami dapat mengenali tugas-tugas umum, seperti memperlihatkan daftar dari obyek, dan menulis kode yang memperlihatkan daftar dari obyek *apapun*. Kemudian model di pertanyaan dapat dilewatkan sebagai sebuah argumen tambahan pada URLconf.

Django dibungkus dengan tampilan umum untuk melakukan berikut:

- Memperlihatkan daftar dan halaman rincian untuk obyek tunggal. Jika kami sedang membuat sebuah aplikasi untuk mengelola pertemuan kemudian `TalkListView` dan `RegisteredUserListView` akan menjadi contoh dari daftar tampilan. Halaman percakapan tunggal adalah sebuah contoh dari apa kami sebut tampilan "detail".
- Obyek berdasarkan-tanggal sekarang di halaman arsip tahun/bulan/hari, rincian terkait, dan halaman "latest".
- Mengizinkan untuk membuat, memperbaharui, dan menghapus obyek -- dengan atau tanpa otorisasi.

Taken together, these views provide interfaces to perform the most common tasks
developers encounter.

## Memperpanjang tampilan umum

Tidak ada pertanyaan yang menggunakan tampilan umum yang dapat mempercepat pengembangan besar. Dalam kebanyakan proyek, bagaimanapun, ada datang saat ketika tampilan umum tidak lagi cukup. Memang, pertanyaan paling umum ditanyakan oleh pengembang Django baru adalah bagaimana membuat tampilan umum menangangi larik lebih lebar dari keadaan.

This is one of the reasons generic views were redesigned for the 1.3 release -
previously, they were view functions with a bewildering array of options; now,
rather than passing in a large amount of configuration in the URLconf, the
recommended way to extend generic views is to subclass them, and override their
attributes or methods.

Itu dikatakan, tampilan umum akan mempunyai sebuah batasan. Jika anda menemukan anda sedang berjuang menerapkan tampilan anda sebagai sebuah subkelas dari tampilan umum, kemudian anda mungkin menemukan itu lebih efektif untuk menulis hanya kode anda butuhkan, menggunakan berdasarkan-kelas anda sendiri atau tampilan kegunaan.

Contoh-contoh lebih dari tampilan umum tersedia di beberapa aplikasi pihak ketiga, atau anda dapat menulis anda sendiri sesuai kebutuhan.

## Tampilan umum dari obyek

[`TemplateView`](/id/5.1/ref/class-based-views/base/#django.views.generic.base.TemplateView) certainly is useful, but
Django's generic views really shine when it comes to presenting views of your
database content. Because it's such a common task, Django comes with a handful
of built-in generic views to help generate list and detail views of objects.

Mari kita mulai dengan mencari beberapa contoh dari menunjukkan daftar dari obyek atau obyek tersendiri.

Kami akan menggunakan model ini

```
# models.py
from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    class Meta:
        ordering = ["-name"]

    def __str__(self):
        return self.name

class Author(models.Model):
    salutation = models.CharField(max_length=10)
    name = models.CharField(max_length=200)
    email = models.EmailField()
    headshot = models.ImageField(upload_to="author_headshots")

    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField("Author")
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
    publication_date = models.DateField()
```

Sekarang kami butuh menentukan sebuah tampilan:

```
# views.py
from django.views.generic import ListView
from books.models import Publisher

class PublisherListView(ListView):
    model = Publisher
```

Akhirnya kaitkan tampilan itu kedalam url anda

```
# urls.py
from django.urls import path
from books.views import PublisherListView

urlpatterns = [
    path("publishers/", PublisherListView.as_view()),
]
```

That's all the Python code we need to write. We still need to write a template,
however. We could explicitly tell the view which template to use by adding a
`template_name` attribute to the view, but in the absence of an explicit
template Django will infer one from the object's name. In this case, the
inferred template will be `"books/publisher_list.html"` -- the "books" part
comes from the name of the app that defines the model, while the "publisher"
bit is the lowercased version of the model's name.

> **Note**
>
> Dengan demikian, ketika (sebagai contoh) pilihan `APP_DIRS` dari backend `DjangoTemplates` disetel menjadi True di [`TEMPLATES`](/id/5.1/ref/settings/#std-setting-TEMPLATES), tempat cetakan dapat berupa: /path/to/project/books/templates/books/publisher\_list.html

This template will be rendered against a context containing a variable called
`object_list` that contains all the publisher objects. A template might look
like this:

```html+django
{% extends "base.html" %}

{% block content %}
    <h2>Publishers</h2>
    <ul>
        {% for publisher in object_list %}
            <li>{{ publisher.name }}</li>
        {% endfor %}
    </ul>
{% endblock %}
```

Itu semua benar-benar ada adalah pada itu. Semua fitur-fitur keren dari tampilan umum datang dari merubah atribut disetel pada tampilan umum. [generic views reference](/id/5.1/ref/class-based-views/) mendokumentasikan semua tampilan umum dan pilihan mereka di rincian; sisa dari dokumen ini akan dianggap beberapa dari cara umum anda mungkin menyesuaikan dan memperpanjang tampilan umum.

### Membuat konteks cetakan "friendly"

Anda mungkin telah memperhatikan bahwa contoh cetakan daftar penerbit kami menyimpan semua penerbit dalam sebuah variabel bernama `object_list`. Selagi ini bekerja baik, itu tidak semua yang "friendly" pada cetakan penulis: mereka harus "just know" bahwa mereka sedang berurusan dengan penerbit disini.

Well, if you're dealing with a model object, this is already done for you. When
you are dealing with an object or queryset, Django is able to populate the
context using the lowercased version of the model class' name. This is provided
in addition to the default `object_list` entry, but contains exactly the same
data, i.e. `publisher_list`.

Jika ini masih tidak kecocokan baik, anda dapat manual menyetel nama dari variabel konteks. Atribut `context_object_name` pada tampilan umum menentukan variabel konteks untuk digunakan:

```
# views.py
from django.views.generic import ListView
from books.models import Publisher

class PublisherListView(ListView):
    model = Publisher
    context_object_name = "my_favorite_publishers"
```

Menyediakan sebuah `context_object_name` berguna selalu ide bagus. Rekan kerja anda yang merancang cetakan akan berterima kasih.

### Menambahkan konteks tambahan

Often you need to present some extra information beyond that provided by the
generic view. For example, think of showing a list of all the books on each
publisher detail page. The [`DetailView`](/id/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView)
generic view provides the publisher to the context, but how do we get
additional information in that template?

The answer is to subclass [`DetailView`](/id/5.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView)
and provide your own implementation of the `get_context_data` method.
The default implementation adds the object being displayed to the template, but
you can override it to send more:

```
from django.views.generic import DetailView
from books.models import Book, Publisher

class PublisherDetailView(DetailView):
    model = Publisher

    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        # Add in a QuerySet of all the books
        context["book_list"] = Book.objects.all()
        return context
```

> **Note**
>
> Umumnya, `get_context_data` akan menggabungkan data konteks dari semua induk kelas dengan mereka dari kelas saat ini. Untuk mempertahankan kebiasaan ini di kelas milik anda sendiri dimana anda ingin merubah konteks, anda harus pasti memanggil `get_context_data` pada super kelas. Ketika tidak ada dua kelas mencoba menentukan kunci yang sama, ini akan memberikan hasil yang diharapkan. Bagaimanapun jika tiap kelas mencoba menimpa kunci setelah kelas induk menyetelnya (setelah panggilan pada super), tiap anak dari kelas akan juga butuh secara eksplisit menyetelnya setelah super jika mereka ingin memastikan untuk menimpa semua induk. Jika anda mempunyai masalah, tinjau kembali urutan pemecahan metode dari tampilan anda.
>
> Pertimbangan lain adalah bahwa data konteks dari tampilan umum berdasarkan-kelas akan menimpa data disediakan oleh pengolah konteks; lihat [`get_context_data()`](/id/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_context_data) untuk sebuah contoh.

### Menampilkan subkumpulan dari obyek

Sekarang mari kita lebih dekat melihat pada argumen `model` kami telah sepanjang gunakan. Argumen `model`, yang menentukan model basisdata yang tampilan akan beroperasi, tersedia pada seua tampilan umum yang beroperasi pada obyek tunggal atau kumpulan dari obyek. Bagaimanapun, argumen `model` tidak hanya cara untuk menentukan obyek yang tampilan akan beroperasi -- anda dapat juga menentukan daftar dari obyek menggunakan argumen `queryset`:

```
from django.views.generic import DetailView
from books.models import Publisher

class PublisherDetailView(DetailView):
    context_object_name = "publisher"
    queryset = Publisher.objects.all()
```

Specifying `model = Publisher` is shorthand for saying `queryset =
Publisher.objects.all()`. However, by using `queryset` to define a filtered
list of objects you can be more specific about the objects that will be visible
in the view (see [Membuat query](/id/5.1/topics/db/queries/) for more information about
[`QuerySet`](/id/5.1/ref/models/querysets/#django.db.models.query.QuerySet) objects, and see the
[class-based views reference](/id/5.1/ref/class-based-views/) for the
complete details).

Untuk mengambil sebuah contoh, kami mungkin ingin memesan buku berdasarkan tanggal terbitan, dengan yang paling baru dahulu:

```
from django.views.generic import ListView
from books.models import Book

class BookListView(ListView):
    queryset = Book.objects.order_by("-publication_date")
    context_object_name = "book_list"
```

That's a pretty minimal example, but it illustrates the idea nicely. You'll
usually want to do more than just reorder objects. If you want to present a
list of books by a particular publisher, you can use the same technique:

```
from django.views.generic import ListView
from books.models import Book

class AcmeBookListView(ListView):
    context_object_name = "book_list"
    queryset = Book.objects.filter(publisher__name="ACME Publishing")
    template_name = "books/acme_list.html"
```

ikan bahwa selama dengan `queryset` disaring, kami juga menggunakan nama cetakan penyesuaian. Jika kami tidak, tampilan umum akan menggunakan cetakan sama seperti daftar obyek "vanilla", yang mungkin tidak kita inginkan.

Juga perharikan bahwa ini bukan cara sangat elegan dari melakukan buku khusus-penerbit. Jika kami ingin menambah halaman penerbit lain, kami butuh bantuan lain dari baris di URLconf, dan lebih dari sedikit penerbit akan mendapatkan alasan tidak masuk akal. Kami akan berurusan dengan masalah ini di bagian selanjutnya.

> **Note**
>
> Jika anda mendapatkan sebuah 404 ketika meminta `/books/acme/`, periksa untuk memastikan anda sebenarnya mempunyai sebuah Publisher dengan nama 'ACME Publishing'. Tampilan umum mempunyai sebuah parameter `allow_empty` untuk kasus ini. Lihat [class-based-views reference](/id/5.1/ref/class-based-views/) untuk rincian.

### Menyaring dinamis

Kebutuhan umum lain adalah menyaring kebawah obyek yang diberikan di halaman daftar dengan beberapa kunci di URL. Awalnya kami mengkode-keraskan nama penerbit di URLconf, tetapi apa jika kami ingin menulis sebuah tampilan yang menampilkan semua buku oleh beberapa penerbit berubah-ubah?

Handily, the `ListView` has a
[`get_queryset()`](/id/5.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset) method we
can override. By default, it returns the value of the `queryset` attribute,
but we can use it to add more logic.

Bagian kunci membiat ini bekerja adalah bahwa ketika tampilan berdasarkan-kelas dipanggil, beragam hal-hal berguna disimpan di `self`; sama halnya permintaan (`self.request`) ini menyertakan penempatan (`self.args`) dan argumen (`self.kwargs`) berdasarkan-nama menurut URLconf.

Disini, kami mempunyai URLconf dengan kelompok ditangkap tunggal:

```
# urls.py
from django.urls import path
from books.views import PublisherBookListView

urlpatterns = [
    path("books/<publisher>/", PublisherBookListView.as_view()),
]
```

Next, we'll write the `PublisherBookListView` view itself:

```
# views.py
from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from books.models import Book, Publisher

class PublisherBookListView(ListView):
    template_name = "books/books_by_publisher.html"

    def get_queryset(self):
        self.publisher = get_object_or_404(Publisher, name=self.kwargs["publisher"])
        return Book.objects.filter(publisher=self.publisher)
```

Using `get_queryset` to add logic to the queryset selection is as convenient
as it is powerful. For instance, if we wanted, we could use
`self.request.user` to filter using the current user, or other more complex
logic.

Kami dapat juga menambahkan penerbit kedalam konteks pada waktu bersamaan, jadi kami dapat menggunakannya di cetakan:

```
# ...

def get_context_data(self, **kwargs):
    # Call the base implementation first to get a context
    context = super().get_context_data(**kwargs)
    # Add in the publisher
    context["publisher"] = self.publisher
    return context
```

### Melakukan pekerjaan tambahan

Pola umum terakhir kami akan lihat pada melibatkan melakukan beberapa pekerjaan tambahan sebelum atau sesudah memanggil tampilan umum.

Bayangkan kami mempunyai sebuah bidang `last_accessed` di model `Author` kami yang kami sedang gunakanuntuk menjaga lintas dari waktu terakhir siapapun mencari penulis itu:

```
# models.py
from django.db import models

class Author(models.Model):
    salutation = models.CharField(max_length=10)
    name = models.CharField(max_length=200)
    email = models.EmailField()
    headshot = models.ImageField(upload_to="author_headshots")
    last_accessed = models.DateTimeField()
```

The generic `DetailView` class wouldn't know anything about this field, but
once again we could write a custom view to keep that field updated.

Pertama, kami butuh menambah rincian seorang penulis sedikit dalam URLconf untuk menunjuk pada tampilan penyesuaian:

```
from django.urls import path
from books.views import AuthorDetailView

urlpatterns = [
    # ...
    path("authors/<int:pk>/", AuthorDetailView.as_view(), name="author-detail"),
]
```

Kemudian kami akan menulis tampilan baru kami -- `get_object` adalah metode yang mengambil objek -- jadi kami menimpanya dan mengakhiri panggilan:

```
from django.utils import timezone
from django.views.generic import DetailView
from books.models import Author

class AuthorDetailView(DetailView):
    queryset = Author.objects.all()

    def get_object(self):
        obj = super().get_object()
        # Record the last accessed date
        obj.last_accessed = timezone.now()
        obj.save()
        return obj
```

> **Note**
>
> URLconf disini menggunakan kelompok bernama `pk` \- nama ini adalah nama awalan yang `DetailView` menggunakan untuk menemukan nilai dari primary key digunakan untuk menyaring queryset.
>
> If you want to call the group something else, you can set
> [`pk_url_kwarg`](/id/5.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.pk_url_kwarg)
> on the view.
