# Dokumentasi Django 5.2.8

# Situs admin Django

Satu dari bagian yang paling berkuasa dari Django adalah antarmuka admin otomatis. Itu membaca metadata dari model anda untuk menyediakan cepat, antarmuka terpusat-model dimana pengguna dipercaya dapat mengelola isi pada situs anda. Dianjurkan admin menggunakan batasannya ke sebuah alat pengelola internal organisasi. Itu tidak dimaksudkan untuk membangun keseluruhan front end disekeliling.

Admin mempunyai banyak kaitan untuk penyesuaian, tetapi hati-hati dari mencoba menggunakan kaitan tersebut secara khusus. Jika anda butuh menyediakan antarmuka pengolahan-terpusat yang memisahkan rincian penerapan dari tabel-tabel dan bidang-bidang basisdata, kemudian itu mungkin waktu utuk menulis tampilan anda sendiri.

Di dokumen ini kami mengobrol bagaimana mengaktifkan pengguna, menggunakan, dan menyesuaikan antarmuka admin Django.

## Ikhtisar

Admin diadakan di cetakan proyek awalan digunakan oleh `startproject`.

Jika anda tidak menggunakan cetakan proyek awalan, ini adalah syarat-syaratnya:

1. Tambah `'django.contrib.admin'` dan ketergantungannya - `django.contrib.auth`, `django.contrib.contenttypes`, `django.contrib.messages`, dan `django.contrib.sessions` - ke pengaturan `INSTALLED_APPS`.

2. Configure a `DjangoTemplates` backend in your `TEMPLATES` setting with `django.template.context_processors.request`, `django.contrib.auth.context_processors.auth`, and `django.contrib.messages.context_processors.messages` in the `'context_processors'` option of `OPTIONS`.

3. If you've customized the `MIDDLEWARE` setting, `django.contrib.sessions.middleware.SessionMiddleware`, `django.contrib.auth.middleware.AuthenticationMiddleware`, and `django.contrib.messages.middleware.MessageMiddleware` must be included.

4. Hook the admin's URLs into your URLconf.

Setelah anda mengambil langkah-langkah ini, anda mungkin akan dapat menggunakan situs admin dengan mengunjungi URL anda kaitkan kedalam (`/admin/`, secara awalan).

If you need to create a user to login with, use the `createsuperuser` command. By default, logging in to the admin requires that the user has the `is_staff` attribute set to `True`.

Akhirnya, tentukan mana model aplikasi anda harus disunting dalam antarmuka admin. Untuk setiap dari model tersebut, daftarkan mereka dengan admin seperti digambarkan dalam `ModelAdmin`.

### Topik lainnya

- Tindakan admin
- `ModelAdmin` List Filters
- Pembangkit dokumentasi admin Django
- Penyesuaian JavaScript di admin

Lihat juga

Untuk informasi tentang melayani berkas-berkas tetap (gambar, JavaScript, dan CSS) terhubung dengan admin di produksi, lihat Melayani berkas.

Mempunyai masalah? Coba FAQ: Admin.

## Obyek `ModelAdmin`

class ModelAdmin

  The `ModelAdmin` class is the representation of a model in the admin interface. Usually, these are stored in a file named `admin.py` in your application. Let's take a look at an example of the `ModelAdmin`:

      from django.contrib import admin
      from myapp.models import Author

      class AuthorAdmin(admin.ModelAdmin):
          pass

      admin.site.register(Author, AuthorAdmin)

  Apakah anda butuh sebuah obyek `ModelAdmin` sama sekali?

  Di contoh terdahulu, kelas `ModelAdmin` tidak menentukan nilai-nilai penyesuaian apapun (pun). Sebagai hasil, awalan antarmuka admin akan disediakan. Jika anda senang dengan awalan antarmuka admin, anda tidak butuh menentukan sebuah obyek `ModelAdmin` sama sekali -- anda dapat mendafta kelas model tanpa menyediakan sebuah gambaran `ModelAdmin`. Contoh terdahulu dapat disederhanakan menjadi:

      from django.contrib import admin
      from myapp.models import Author

      admin.site.register(Author)

### Penghias `register`

register(*models, site=django.contrib.admin.sites.site)

  Ada juga sebuah penghias untuk mendaftarkan kelas-kelas `ModelAdmin` anda:

      from django.contrib import admin
      from .models import Author

      @admin.register(Author)
      class AuthorAdmin(admin.ModelAdmin):
          pass

  Itu diberikan satu atau lebih kelas-kelas model untuk didaftarkan dengan `ModelAdmin`. Jika anda sedang menggunakan penyesuaian `AdminSite`, lewatkan itu menggunakan argumen katakunci `site`:

      from django.contrib import admin
      from .models import Author, Editor, Reader
      from myproject.admin_site import custom_admin_site

      @admin.register(Author, Reader, Editor, site=custom_admin_site)
      class PersonAdmin(admin.ModelAdmin):
          pass

  Anda tidak dapat menggunakan decorator ini jika anda harus mengacu kelas admin anda dalam metode `__init__()` nya, misalnya. `super(PersonAdmin, self).__init__(*args, **kwargs)`. Anda dapat menggunakan `super().__init__(*args, **kwargs)`.

### Penemuan dari berkas admin

Ketika anda menaruh `'django.contrib.admin'` di pengaturan `INSTALLED_APPS` anda, Django secara otomatis mencari modul `admin` di setiap aplikasi dan mengimpor itu.

class apps.AdminConfig

  This is the default `AppConfig` class for the admin. It calls `autodiscover()` when Django starts.

class apps.SimpleAdminConfig

  This class works like `AdminConfig`, except it doesn't call `autodiscover()`.

  default_site

    Jalur impor bertitik pada kelas situs admin awalan atau pada callable yang mengembalikan yang mengembalikan sebuah instance situs. Awalan pada `'django.contrib.admin.sites.AdminSite'`. Lihat Menimpa situs admin awalan untuk penggunaan.

autodiscover()

  Fungsi ini berusaha mengimpor sebuah modul `admin` di setiap aplikasi terpasang. Modul-modul itu diharapkan mendaftar model dengan admin.

  Secara khusus anda tidak butuh memanggil fungsi ini secara langsung sebagai `AdminConfig` memanggilnya ketika Django mulai.

Jika anda sedang menggunakan sebuah penyesuaian `AdminSite`, itu adalah umum mengimpor semua dari subkelas `ModelAdmin` kedalam kode anda dan mendaftarkan mereka ke penyesuaian `AdminSite`. Dalam hal itu, untuk meniadakan penemuan-otomatis, anda harus menaruh `'django.contrib.admin.apps.SimpleAdminConfig'` sebagai gantinya `'django.contrib.admin'` di pengaturan `INSTALLED_APPS` anda.

### Pilihan `ModelAdmin`

`ModelAdmin` sangat fleksibel. Itu mempunyai beberapa pilihan untuk berurusan dengan menyesuaikan antarmuka. Semua pilihan ditentukan pada subkelas `ModelAdmin`:

    from django.contrib import admin

    class AuthorAdmin(admin.ModelAdmin):
        date_hierarchy = "pub_date"

ModelAdmin.actions

  Sebuah daftar tindakan untuk membuat tersedia pada halaman daftar perubahan. Lihat Tindakan admin untuk rincian.

ModelAdmin.actions_on_top

ModelAdmin.actions_on_bottom

  Kendalikan dimana pada halaman batang tindakan muncul. Secara awalan daftar rubah admin memperlihatkan tindakan pada atas dari halaman (`actions_on_top = True; actions_on_bottom = False`).

ModelAdmin.actions_selection_counter

  Kendalikan apakah sebuah penghitung pemilihan ditampilkan dekat tindakan dropdown. Secara awalan, daftar tubadh admin akan memperlihatkan itu (`actions_selection_counter = True`).

ModelAdmin.date_hierarchy

  Setel `date_hierarchy` pada nama dari `DateField` atau `DateTimeField` di model anda, dan halaman daftar rubah akan menyertakan navigasi penelusuran berdasarkan-tanggal oleh bidang itu.

  Contoh:

      date_hierarchy = "pub_date"

  Anda dapat juga menentukan sebuah bidang pada model terkait menggunakan pencarian `__`, sebagai contoh:

      date_hierarchy = "author__pub_date"

  Ini akan secara cerdas mengumpulkan itu sendiri berdasarkan pada data tersedia, misalnya jika semua tanggal berada di satu bulan, itu akan menampilkan hanya penelesuran tingkat-hari.

  Catatan

  `date_hierarchy` menggunakan `QuerySet.datetimes()` secara internal. Harap mengacu ke dokumentasinya untuk beberapa peringatan ketika dukungan zona waktu diadakan (`USE_TZ = True`).

ModelAdmin.empty_value_display

  Atribut ini menimpa nilai pertunjukan awalan untuk bidang rekaman yang kosong (`None`, string kosong, dll). Nilai awalan `-` (sebuah tanda garis). Sebagai contoh:

      from django.contrib import admin

      class AuthorAdmin(admin.ModelAdmin):
          empty_value_display = "-empty-"

  Anda dapat juga menimpa `empty_value_display` untuk semua halaman admin dengan `AdminSite.empty_value_display`, atau bidang-bidang tertentu seperti ini:

      from django.contrib import admin

      class AuthorAdmin(admin.ModelAdmin):
          list_display = ["name", "title", "view_birth_date"]

          @admin.display(empty_value="???")
          def view_birth_date(self, obj):
              return obj.birth_date

ModelAdmin.exclude

  Atribut ini, jika diberikan, harus berupa daftar dari nama-nama bidang untuk mengeluarkan dari formulir.

  Sebagai contoh, mari kita pertimbangkan model berikut:

      from django.db import models

      class Author(models.Model):
          name = models.CharField(max_length=100)
          title = models.CharField(max_length=3)
          birth_date = models.DateField(blank=True, null=True)

  Jika anda ingin sebuah formulit untuk model `Author` yang menyertakan hanya bidang `name` dan `title`, anda akan menentukan `fields` atau `exclude` seperti ini:

      from django.contrib import admin

      class AuthorAdmin(admin.ModelAdmin):
          fields = ["name", "title"]

      class AuthorAdmin(admin.ModelAdmin):
          exclude = ["birth_date"]

  Sejak model Author hanya mempunyai tiga bidang, `name`, `title`, dan `birth_date`, formulir dihasilkan dari pernyataan diatas akan mengandung bidang-bidang sama persis.

ModelAdmin.fields

  Gunakan pilihan `fields` untuk membuat perubahan tata letak sederhana di formulir pada halaman "add" dan "change" seperti menunjukkan hanya subhimpunan dari bidang-bidang tersedia, merubah urutan mereka, atau mengelompokkan mereka kedalam baris. Sebagai contoh, anda dapat menentukan versi sederhana dari formulir admin untuk model `django.contrib.flatpages.models.FlatPage` seperi berikut:

      class FlatPageAdmin(admin.ModelAdmin):
          fields = ["url", "title", "content"]

  Di contoh diatas, hanya bidang-bidang `url`, `title` dan `content` akan diperlihatkan, berurutan, di formulir. `fields` dapat mengandung nilai-nilai ditentukan di `ModelAdmin.readonly_fields` untuk diperlihatkan sebagai hanya-baca.

  Untuk kebutuhan tata letak lebih rumit, lihat pilihan `fieldsets`.

  The `fields` option accepts the same types of values as `list_display`, except that callables and `__` lookups for related fields aren't accepted. Names of model and model admin methods will only be used if they're listed in `readonly_fields`.

  Untuk memperlihatkan banyak bidang pada baris yang sama, bungkus bidang-bidang tersebut di tuple mereka sendiri. Di contoh ini, bidang `url` dan `title` akan diperlihatkan di baris sama dan bidang `content` akan diperlihatkan dibawah mereka pada baris nya sendiri:

      class FlatPageAdmin(admin.ModelAdmin):
          fields = [("url", "title"), "content"]

  Possible confusion with the `ModelAdmin.fieldsets` option

  Pilihan `fields` ini tidak harus membingungkan dengan kunci kamus `fields` yaitu dalam pilihan `fieldsets`, seperti digambarkan di bagian selanjutnya.

  If neither `fields` nor `fieldsets` options are present, Django will default to displaying each field that isn't an `AutoField` and has `editable=True`, in a single fieldset, in the same order as the fields are defined in the model, followed by any fields defined in `readonly_fields`.

ModelAdmin.fieldsets

  Setel `fieldsets` utuk mengendalikan tata letak dari halaman "add" dan "change" admin.

  `fieldsets` is a list of 2-tuples, in which each 2-tuple represents a `<fieldset>` on the admin form page. (A `<fieldset>` is a "section" of the form.)

  The 2-tuples are in the format `(name, field_options)`, where `name` is a string representing the title of the fieldset and `field_options` is a dictionary of information about the fieldset, including a list of fields to be displayed in it.

  Sebuah contoh penuh, diambil dari model `django.contrib.flatpages.models.FlatPage`

      from django.contrib import admin

      class FlatPageAdmin(admin.ModelAdmin):
          fieldsets = [
              (
                  None,
                  {
                      "fields": ["url", "title", "content", "sites"],
                  },
              ),
              (
                  "Advanced options",
                  {
                      "classes": ["collapse"],
                      "fields": ["registration_required", "template_name"],
                  },
              ),
          ]

  Hasil dalam halaman admin yang kelihatan seperti:

  Jika tidak ada pilihan `fieldsets` maupun `fields` hadir, Django akan mengawalkan ke menampilkan setiap bidang yang bukan sebuah `AutoField` dan mempunyai `editable=True`, dalam fieldset tunggal, di urutan sama seperti bidang-bidang ditentukan di model

  Kamus `field_options` dapat mempunyai kunci berikut:

  - `fields`

      A list or tuple of field names to display in this fieldset. This key is required.

      Contoh:

          {
              "fields": ["first_name", "last_name", "address", "city", "state"],
          }

      Seperti pilihan `fields`, untuk memperlihatkan banyak bidang pada baris sama, membungkus bidang tersebut di tuple mereka sendiri. Dalam contoh ini, bidang `first_name` dan `last_name` memperlihatkan pada baris sama:

          {
              "fields": [("first_name", "last_name"), "address", "city", "state"],
          }

      `fields` dapat mengandung nilai-nilai ditentukan di `readonly_fields` untuk ditampilkan sebagai hanya-baca.

      Jika anda menambah nama dari callable ke `fields`, aturan sama berlaku seperti pilihan `fields`: callable harus sidaftar di `readonly_fields`.

  - `classes`

      A list or tuple containing extra CSS classes to apply to the fieldset. This can include any custom CSS class defined in the project, as well as any of the CSS classes provided by Django. Within the default admin site CSS stylesheet, two particularly useful classes are defined: `collapse` and `wide`.

      Contoh:

          {
              "classes": ["wide", "collapse"],
          }

      Fieldsets with the `wide` style will be given extra horizontal space in the admin interface. Fieldsets with a name and the `collapse` style will be initially collapsed, using an expandable widget with a toggle for switching their visibility.

  - `description`

      A string of optional extra text to be displayed at the top of each fieldset, under the heading of the fieldset.

      Catat bahwa nilai ini bukan pelolosan-HTML ketika itu ditampilkan dalam antarmuka admin. Ini membuat anda menyertakan HTML jika anda inginkan. Cara lain anda dapat menggunakan teks polos dan `django.utils.html.escape()` untuk meloloskan karakter khusus HTML apapun.

  `TabularInline` has limited support for `fieldsets`

  Using `fieldsets` with `TabularInline` has limited functionality. You can specify which fields will be displayed and their order within the `TabularInline` layout by defining `fields` in the `field_options` dictionary.

  All other features are not supported. This includes the use of `name` to define a title for a group of fields.

ModelAdmin.filter_horizontal

  Secara awalan, sebuah `ManyToManyField` diperlihatkan di situs admin dengan `<select multiple>`. Bagaimanapun, kotak pilihan-banyak dapat sulit digunakan ketika memilih banyak barang. Menambahkan sebuah `ManyToManyField` ke daftar ini malahan akan menggunakan antarmuka "filter" JavaScript tidak mengganggu yang mengizinkan pencarian dalam pilihan. Pilihan tidak terpilih atau terpilih muncul di dua kotak bersebelahan. Lihat `filter_vertical` untuk menggunakan antarmuka tegak lurus.

ModelAdmin.filter_vertical

  Sama seperti `filter_horizontal`, tetapi menggunakan tampilan tegak lurus dari antarmuka penyaring dengan kotak dari piliha tidak dipilih muncul diatas dari pilihan terpilih.

ModelAdmin.form

  Secara awalan sebuah `ModelForm` secara dinamis dibuat untuk model anda. Itu digunakan untuk membuat formulir dihadirkan pada kedua halaman tambah/rubah. Anda dapat dengan mudah menyediakan `ModelForm` anda sendiri untuk menimpa awalan perilaku formulir apapun pada halaman tambah/rubah. Kalau tidak, anda dapat menyesuaikan awalan formulir daripada menentukan keseluruhan satu yang baru menggunakan metode `ModelAdmin.get_form()`.

  Untuk sebuah contoh lihat bagian Menambahkan pengesahan penyesuaian pada admin.

  Omit the `Meta.model` attribute

  Jika anda menentukan atribut `Meta.model` pada sebuah `ModelForm`, anda harus juga menentukan atribut `Meta.fields` (atau atribut `Meta.exclude`). Bagaimanapun, sejak admin mempunyai caranya sendiri dari menentukan bidang-bidang, atribut `Meta.fields` akan diabaikan.

  Jika `ModelForm` hanya akan digunakan untuk admin, pemecahan termudah adalah mengilangkan atribut `Meta.model`, sejak `ModelAdmin` akan menyediakan model benar untuk digunakan. Kalau tidak, anda dapat menyetel `fields = []` di kelas `Meta` untuk memuaskan pengesahan pada `ModelForm`.

  `ModelAdmin.exclude` takes precedence

  Jika `ModelForm` dan `ModelAdmin` kedua menentukan sebuah pilihan `exclude` kemudian `ModelAdmin` mengambil mendahului:

      from django import forms
      from django.contrib import admin
      from myapp.models import Person

      class PersonForm(forms.ModelForm):
          class Meta:
              model = Person
              exclude = ["name"]

      class PersonAdmin(admin.ModelAdmin):
          exclude = ["age"]
          form = PersonForm

  Dalam contoh diatas, bidang "age" akan tidak disertakan tetapi bidang "name: akan disertakan di formulir dibangkitkan.

ModelAdmin.formfield_overrides

  Ini menyediakan cara cepat-dan-kotor untuk menimpa beberapa pilihan `Field` untuk digunakan di admin. `formfield_overrides` adalah sebuah kamus memetakan sebuah kelas bidang pada kamus dari argumen untuk melewatkan ke bidang pada waktu pembangunan.

  Sejak itu sedikit abstrak, mari kita lihat contoh nyata. Penggunaan paling umum dari `formfield_overrides` ada;ah menambahkan sebuah widget penyesuaian untuk jenis tertentu dari bidang. Jadi, bayangkan kami telah menulis sebuah `RichTextEditorWidget` yang ingin untuk digunakan untuk bidang teks besar daripada awalan `<textarea>`. Ini adalah bagaimana kami melakukannya:

      from django.contrib import admin
      from django.db import models

      # Import our custom widget and our model from where they're defined
      from myapp.models import MyModel
      from myapp.widgets import RichTextEditorWidget

      class MyModelAdmin(admin.ModelAdmin):
          formfield_overrides = {
              models.TextField: {"widget": RichTextEditorWidget},
          }

  Catat bahwa kunci di kamus adalah kelas bidang sebenarnya, bukan sebuah string. Nilai adalah kamus lain; argumen ini akan dilewatkan ke metode `__init__()` bidang formulir. Lihat API Formulir untuk rincian.

  Peringatan

  Jika anda ingin menggunakan sebuah widget penyesuaian dengan sebuah bidang hubungan (yaitu `ForeignKey` atau `ManyToManyField`), pastikan anda belum menyertakan nama bidang tersebut dalam `raw_id_fields`, `radio_fields`, or `autocomplete_fields`.

  `formfield_overrides` tidak akan membiarkan anda merubah widget pada bidang hubungan yang memiliki kumpulan `raw_id_fields`, `radio_fields`, atau `autocomplete_fields`. Itu karena `raw_id_fields`, `radio_fields`, dan `autocomplete_fields` berarti widget penyesuaian dari mereka sendiri.

ModelAdmin.inlines

  Lihat `InlineModelAdmin` objects below as well as `ModelAdmin.get_formsets_with_inlines()`.

ModelAdmin.list_display

  Set `list_display` untuk mengendalikan bidang-bidang mana yang ditampilkan pada halaman daftar rubah dari admin.

  Contoh:

      list_display = ["first_name", "last_name"]

  Jika anda tidak menyetel `list_display`, situs admin akan menampilkan kolom tunggal yang menampilkan perwakilan `__str__()` untuk setiap obyek.

  There are five types of values that can be used in `list_display`. All but the simplest may use the `display()` decorator, which is used to customize how the field is presented:

  - Nama dari bidang model. Sebagai contoh:

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["first_name", "last_name"]

  - The name of a related field, using the `__` notation. For example:

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["city__name"]

  - Sebuah callable yang menerima satu argumen, instance model. Sebagai contoh:

        @admin.display(description="Name")
        def upper_case_name(obj):
            return f"{obj.first_name} {obj.last_name}".upper()

        class PersonAdmin(admin.ModelAdmin):
            list_display = [upper_case_name]

  - Sebuah string mewakili sebuah metode `ModelAdmin` yang menerima satu argumen. instance model. Sebagai contoh:

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["upper_case_name"]

            @admin.display(description="Name")
            def upper_case_name(self, obj):
                return f"{obj.first_name} {obj.last_name}".upper()

  - Sebuah string mewakilkan sebuah atribut model atau metode (tanpa argumen dibutuhkan apapun). Sebagai contoh:

        from django.contrib import admin
        from django.db import models

        class Person(models.Model):
            name = models.CharField(max_length=50)
            birthday = models.DateField()

            @admin.display(description="Birth decade")
            def decade_born_in(self):
                decade = self.birthday.year // 10 * 10
                return f"{decade}’s"

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["name", "decade_born_in"]

  Sedikit kasus khusus untuk dicatat tentang `list_display`:

  - Jika bidang adalah sebuah `ForeignKey`, Django akan menampilkan `__str__()` dari obyek terkait.

  - Bidang-bidang `ManyToManyField` tidak didukung, karena akan memerlukan mengerjakan pernyataan SQL terpisah untuk setiap baris di tabel. Jika anda ingin melakukan ini meskipun begitu, berikan model anda sebuah metode penyesuaian, dan tambah nama metode ke `list_display`. (Lihat dibawah untuk lebih pada metode penyesuaian di `list_display`.)

  - If the field is a `BooleanField`, Django will display a pretty "yes", "no", or "unknown" icon instead of `True`, `False`, or `None`.

  - Jika deretan karakter yang diberikan adalah metode dari model, `ModelAdmin` atau callable, Django akan meloloskan-HTML keluaran secara awalan. Untuk meloloskan masukan pengguna dan mengizinkan etiket tidak meloloskan anda sendiri, gunakan `format_html()`.

    Ini adalah sebuah contoh penuh model:

        from django.contrib import admin
        from django.db import models
        from django.utils.html import format_html

        class Person(models.Model):
            first_name = models.CharField(max_length=50)
            last_name = models.CharField(max_length=50)
            color_code = models.CharField(max_length=6)

            @admin.display
            def colored_name(self):
                return format_html(
                    '<span style="color: #{};">{} {}</span>',
                    self.color_code,
                    self.first_name,
                    self.last_name,
                )

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["first_name", "last_name", "colored_name"]

  - As some examples have already demonstrated, when using a callable, a model method, or a `ModelAdmin` method, you can customize the column's title by wrapping the callable with the `display()` decorator and passing the `description` argument.

  - Jika nilai dari sebuah bidang adalah `None`, sebuah string kosong, atau sebuah perulangan tanpa unsur-unsur, Django akan menampilkan -` (tanda garis). Anda dapat menimpa ini dengan `AdminSite.empty_value_display`:

        from django.contrib import admin

        admin.site.empty_value_display = "(None)"

    Anda juga dapat menggunakan `ModelAdmin.empty_value_display`:

        class PersonAdmin(admin.ModelAdmin):
            empty_value_display = "unknown"

    Atau pada tingkat bidang:

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["name", "birth_date_view"]

            @admin.display(empty_value="unknown")
            def birth_date_view(self, obj):
                return obj.birth_date

  - If the string given is a method of the model, `ModelAdmin` or a callable that returns `True`, `False`, or `None`, Django will display a pretty "yes", "no", or "unknown" icon if you wrap the method with the `display()` decorator passing the `boolean` argument with the value set to `True`:

        from django.contrib import admin
        from django.db import models

        class Person(models.Model):
            first_name = models.CharField(max_length=50)
            birthday = models.DateField()

            @admin.display(boolean=True)
            def born_in_fifties(self):
                return 1950 <= self.birthday.year < 1960

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["name", "born_in_fifties"]

  - Metode `__str__()` adalah hanya sah dalam `list_display` seperti metode model lain apapun, jadi itu sangat OK untuk melakukan ini:

        list_display = ["__str__", "some_other_field"]

  - Biasanya, unsur-unsur dari `list_display` yang bukan bidang basisdata sebenarnya tidak dapat digunakan dalam mengurutkan (karena Django melakukan semua pengurutan pada tingkat basisdata).

    However, if an element of `list_display` represents a certain database field, you can indicate this fact by using the `display()` decorator on the method, passing the `ordering` argument:

        from django.contrib import admin
        from django.db import models
        from django.utils.html import format_html

        class Person(models.Model):
            first_name = models.CharField(max_length=50)
            color_code = models.CharField(max_length=6)

            @admin.display(ordering="first_name")
            def colored_first_name(self):
                return format_html(
                    '<span style="color: #{};">{}</span>',
                    self.color_code,
                    self.first_name,
                )

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["first_name", "colored_first_name"]

    Diatas akan mengatakan Django untuk mengurutkan berdasarkan bidang `first_name` ketika mencoba mengurutkan berdasarkan `colored_first_name` di admin.

    To indicate descending order with the `ordering` argument you can use a hyphen prefix on the field name. Using the above example, this would look like:

        @admin.display(ordering="-first_name")
        def colored_first_name(self): ...

    The `ordering` argument supports query lookups to sort by values on related models. This example includes an "author first name" column in the list display and allows sorting it by first name:

        class Blog(models.Model):
            title = models.CharField(max_length=255)
            author = models.ForeignKey(Person, on_delete=models.CASCADE)

        class BlogAdmin(admin.ModelAdmin):
            list_display = ["title", "author", "author_first_name"]

            @admin.display(ordering="author__first_name")
            def author_first_name(self, obj):
                return obj.author.first_name

    Query expressions may be used with the `ordering` argument:

        from django.db.models import Value
        from django.db.models.functions import Concat

        class Person(models.Model):
            first_name = models.CharField(max_length=50)
            last_name = models.CharField(max_length=50)

            @admin.display(ordering=Concat("first_name", Value(" "), "last_name"))
            def full_name(self):
                return self.first_name + " " + self.last_name

  - Elements of `list_display` can also be properties

        class Person(models.Model):
            first_name = models.CharField(max_length=50)
            last_name = models.CharField(max_length=50)

            @property
            @admin.display(
                ordering="last_name",
                description="Full name of the person",
                boolean=False,
            )
            def full_name(self):
                return self.first_name + " " + self.last_name

        class PersonAdmin(admin.ModelAdmin):
            list_display = ["full_name"]

    Note that `@property` must be above `@display`. If you're using the old way -- setting the display-related attributes directly rather than using the `display()` decorator -- be aware that the `property()` function and not the `@property` decorator must be used:

        def my_property(self):
            return self.first_name + " " + self.last_name

        my_property.short_description = "Full name of the person"
        my_property.admin_order_field = "last_name"
        my_property.boolean = False

        full_name = property(my_property)

  - Nama-nama bidang di `list_display` akan juga muncul sebagai kelas-kelas CSS di keluaran HTML, di formulir dari `column-<field_name>` pada setiap unsur `<th>`. Ini dapat digunakan menyetel lebar kolom di sebuah berkas CSS sebagai contoh.

  - Django akan mencoba mentafsirkan setiap unsur dari `list_display` di urutan ini:

    - A field of the model or from a related field.

    - Callable

    - Sebuah string mewakili sebuah atribut `ModelAdmin`.

    - Sebuah string mewakili sebuah atribut model.

    Sebagai contoh jika anda mempunyai "first name" sebagai model bidang dan sebagai atribut `ModelAdmin`, bidang model akan digunakan.

ModelAdmin.list_display_links

  Gunakan `list_display_links` untuk mengendalikan jika dan bidang-bidang mana di `list_display` harus di tautkan ke halaman "change" untuk sebuah obyek.

  Secara awalan, halaman daftar rubah akan mengkaitkan kolom pertama -- bidang pertama ditentukan di `list_display` -- ke halaman perubahan untuk setiap barang. Tetapi `list_display_links` membiarkan anda merubah ini:

  - Sete itu menjadi `None` untuk tidak mendapatkan tautan sama sekali.

  - Set itu menjadi daftar atau tuple dari bidang (di bentuk sama seperti `list_display`) yang kolomnya anda ingin rubah menjadi tautan.

    Anda dapat menentukan satu atau banyak bidang. Selama bidang-bidang muncul di `list_display`, Django tidak peduli seberapa banyak (seberapa sedikit) bidang-bidang ditautkan. Persyaratan satu-satunya adalah bahwa jika anda ingin menggunakan `list_display_links` dengan cara ini, anda harus menentukan `list_display`.

  Di contoh ini, bidang `first_name` dan `last_name` akan dikaitkan pada halaman daftar rubah:

      class PersonAdmin(admin.ModelAdmin):
          list_display = ["first_name", "last_name", "birthday"]
          list_display_links = ["first_name", "last_name"]

  Di contoh ini, jaring halaman daftar rubah tidak akan mempunyai tautan:

      class AuditEntryAdmin(admin.ModelAdmin):
          list_display = ["timestamp", "message"]
          list_display_links = None

ModelAdmin.list_editable

  Setel `list_editable` ke sebuah daftar nama-nama bidang pada model yang akan mengizinkan menyunting pada halaman daftar rubah. yaitu, bidang-bidang terdaftar di `list_editable` akan diperlihatkan sebagai formulir widget pada halaman daftar rubah, mengizinkan pengguna menyunting dan menyimpan banyak baris sekaligus.

  Catatan

  `list_editable` berinteraksi dengan sepasang dari pilihan lain di cara tertentu; anda harus mencatat peraturan-peraturan berikut:

  - Bidang apapun di `list_editable` harus juga berada di `list_display`. Anda tidak dapat menyunting sebuah bidang yang tidak diperlihatkan!

  - Bidang sama tidak dapat didaftarkan di kedua `list_editable` dan `list_display_links` -- sebuah bidang tidak dapat keduanya sebuah formulir dan sebuah tautan.

  Anda akan mendapatkan sebuah kesalahan pengesahan jika antara peraturan-peraturan ini rusak.

ModelAdmin.list_filter

  Set `list_filter` to activate filters in the right sidebar of the change list page of the admin.

  At it's simplest `list_filter` takes a list or tuple of field names to activate filtering upon, but several more advanced options as available. See ModelAdmin List Filters for the details.

ModelAdmin.list_max_show_all

  Setel `list_max_show_all` untuk mengendalikan seberapa banyak barang dapat muncul pada halaman daftar rubah admin "Show all". Admin akan memperlihatkan sebuah tautan "Show all" pada daftar rubah hanya jika jumlah hasil perhitungan kurang dari atau sama pada pengaturan ini. Secara awalan, ini disetel menjadi `200`.

ModelAdmin.list_per_page

  Setel `list_per_page` untuk mengendalikan seberapa banyak barang akan muncul pada setiap penomoran halaman daftar rubah admin. Secara awalan, ini disetel menjadi `100`.

ModelAdmin.list_select_related

  Setel `list_select_related` untuk memberitahu Django menggunakan `select_related()` dalam mengambil daftar dari obyek-obyek pada halaman daftar rubah admin. Ini dapat menghemat anda sekelompok dari permintaan basisdata.

  Nilai harus antara sebuah boolean, sebuah daftar atau sebuah tuple. Awalan adalah `False`.

  Ketika nilai adalah `True`, `select_related()` akan selalu dipanggil. Ketika nilai disetel menjadi `False`, Django akan mencari `list_display` dan memanggil `select_related()` jika `ForeignKey` apapun hadir.

  Jika anda butuh lebih kendali berjaring-halus, gunakan sebuah tuple (atau daftar) sebagai nilai untuk `list_select_related`. Tuple kosong akan mencegah Django dari memanggil `select_related` sama sekali. Tuple lain apapun akan dilewatkan secara langsung ke `select_related` sebagai parameter. Sebagai contoh:

      class ArticleAdmin(admin.ModelAdmin):
          list_select_related = ["author", "category"]

  akan memanggil `select_related('author', 'category')`.

  Jika anda butuh menentukan nilai dinamis berdasarkan pada permintaan, anda dapat menerapkan cara `get_list_select_related()`.

  Catatan

  `ModelAdmin` mengabaikan atribut ini ketika `select_related()` telah dipanggil pada `QuerySet` daftar rubah.

ModelAdmin.ordering

  Setel `ordering` untuk menentukan bagaimana daftar dari obyek-obyek harus diurutkan di tampilan admin Django. Ini harus berupa sebuah daftar atau tuple di bentuk sama seperti parameter `ordering` model.

  Jika ini tidak disediakan, admin Django akan menggunakan pengurutan awalan model.

  Jika anda butuh menentukan urutan dinamis (sebagai contoh bergantung pada pengguna atau bahasa) anda dapat menerapkan sebuah metode `get_ordering()`.

  Pertimbangan penampilan dengan pengurutan dan pensortiran

  To ensure a deterministic ordering of results, the changelist adds `pk` to the ordering if it can't find a single or unique together set of fields that provide total ordering.

  Sebagai contoh, jika pengurutan awalan adalah dengan bidang `name` bukan-unik, kemudian ubah daftar diurutkan berdasarkan `name` dan `pk`. Ini bisa berkinerja buruk jika anda mempunyai banyak baris dan tidak mempunyai sebuah indeks pada `name` dan `pk`.

ModelAdmin.paginator

  Kelas penomoran digunakan untuk menomorkan halaman. Secara awalan, `django.core.paginator.Paginator` digunakan. Jika penyesuaian kelas penomoran tidak mempunyai antarmuka pembangun sama seperti `django.core.paginator.Paginator`, anda akan juga butuh menyediakan sebuah penerapan untuk `ModelAdmin.get_paginator()`.

ModelAdmin.prepopulated_fields

  Setel `prepopulated_fields` pada nama-nama bidang pemetaan kamus ke bidang-bidang itu harus mengisi dimuka dari:

      class ArticleAdmin(admin.ModelAdmin):
          prepopulated_fields = {"slug": ["title"]}

  When set, the given fields will use a bit of JavaScript to populate from the fields assigned. The main use for this functionality is to automatically generate the value for `SlugField` fields from one or more other fields. The generated value is produced by concatenating the values of the source fields, and then by transforming that result into a valid slug (e.g. substituting dashes for spaces and lowercasing ASCII letters).

  Bidang-bidang diisi tidak dirubah oleh JavaScript setelah sebuah nilai telah disimpan. Itu biasanya tidak diinginkan bahwa tanda siput berubah (yang akan menyebabkan sebuah URL obyek berubah jika tanda siput digunakan dalam itu).

  `prepopulated_fields` tidak menerima bidang-bidang `DateTimeField`, `ForeignKey`, `OneToOneField`, dan `ManyToManyField`.

ModelAdmin.preserve_filters

  By default, applied filters are preserved on the list view after creating, editing, or deleting an object. You can have filters cleared by setting this attribute to `False`.

ModelAdmin.show_facets

  Controls whether facet counts are displayed for filters in the admin changelist. Defaults to `ShowFacets.ALLOW`.

  When displayed, facet counts update in line with currently applied filters.

  class ShowFacets

    Enum of allowed values for `ModelAdmin.show_facets`.

    ALWAYS

      Always show facet counts.

    ALLOW

      Show facet counts when the `_facets` query string parameter is provided.

    NEVER

      Never show facet counts.

  Set `show_facets` to the desired `ShowFacets` value. For example, to always show facet counts without needing to provide the query parameter:

      from django.contrib import admin

      class MyModelAdmin(admin.ModelAdmin):
          ...
          # Have facets always shown for this model admin.
          show_facets = admin.ShowFacets.ALWAYS

  Performance considerations with facets

  Enabling facet filters will increase the number of queries on the admin changelist page in line with the number of filters. These queries may cause performance problems, especially for large datasets. In these cases it may be appropriate to set `show_facets` to `ShowFacets.NEVER` to disable faceting entirely.

ModelAdmin.radio_fields

  Secara awalan, admin Django menggunakan antarmuka kotak-pilih (<select>) untuk bidang-bidang adalah `ForeignKey` atau mempunyai `choices` disetel. Jika sebuah bidang hadir di `radio_fields`, Django akan menggunakan antarmuka tombl-radio sebagai gantinya. Menganggap `group` adalah sebuah `ForeignKey` pada model `Person`:

      class PersonAdmin(admin.ModelAdmin):
          radio_fields = {"group": admin.VERTICAL}

  Anda mempunyai pilihan dari menggunakan `HORIZONTAL` atau `VERTICAL` dari modul `django.contrib.admin`.

  Jangan menyertakan sebuah bidang dalam `radio_fields` meskipun dia adalah `ForeignKey` atau mempunyai kumpulan `choices`.

ModelAdmin.autocomplete_fields

  `autocomplete_fields` adalah sebuah daftar dari `ForeignKey` dan/atau bidang `ManyToManyField` anda ingin rubah menjadi masukan pelengkap otomatis Select2 .

  Secara awalan, admin menggunakan antarmuka pilih-kotak (````) untuk bidang-bidang tersebut. Terkadang anda tidak ingin terjadi tambahan dari memilih semua instance terkait untuk ditampilkan dalam dropdown.

  Masukan Select2 terlihat mirip pada masukan awalan tetapi datang dengan fitur pencarian yang memuat pilihan secara asinkron. Ini lebih cepat dan lebih ramah-pengguna jika model terkait mempunyai banyak instance.

  Anda harus menentukan `search_fields` di obyek `ModelAdmin` terkait karena pencarian lengkap otomatis menggunakan itu.

  Untuk menghindari penyingkapan data tidak berhak, pengguna harus memiliki perizinan `view` atau `change` pada obyek terkait untuk menggunakan pelengkapan otomatis.

  Pengurutan dan penomoran dari hasil dikendalikan oleh metode terkait `get_ordering()` dan `get_paginator()` `ModelAdmin`.

  Dalam contoh berikut, `ChoiceAdmin` mempunyai sebuah bidang pelengkapan otomatis untuk `ForeignKey` pada `Question`. Hasilnya disaring oleh bidang `question_text` diurutkan oleh bidang `date_created`:

      class QuestionAdmin(admin.ModelAdmin):
          ordering = ["date_created"]
          search_fields = ["question_text"]

      class ChoiceAdmin(admin.ModelAdmin):
          autocomplete_fields = ["question"]

  Pertimbangan penampilan untuk kumpulan data besar

  Pengurutan menggunakan `ModelAdmin.ordering` mungkin menyebabkan masalah penampilan seperti pemilihan pada queryset besar akan lambat.

  Juga jika anda mencari bidang yang tidak diindeks oleh basisdata, anda mungkin mengalami penampilan buruk pada table yang sangat besar.

  Untuk kasus-kasus tersebut, adalah ide bagus untuk menulis penerapan `ModelAdmin.get_search_results()` anda sendiri menggunakan pencarian indeks teks-penuh.

  Anda mungkin ingin merubah `Paginator` pada tabel-tabel sangat besar sebagai penomoran awaaln selalu melakukan permintaan `count()`. Sebagai contoh, anda dapat menimpa penerapan dari milik `Paginator.count`.

ModelAdmin.raw_id_fields

  Secara awalan, admin Django menggunakan antarmuka kotak-pilih (<select>) untuk bidang-bidang adalah `ForeignKey`. Terkadang anda tidak ingin mendatangkan atas dari memiliki untuk memilih semua instance terkait untuk memperlihatkan di drop-down.

  `raw_id_fields` adalah sebuah daftar dari bidang anda ingin rubah menjadi widget `input` untuk antara sebuah `ForeignKey` atau `ManyToManyField`:

      class ArticleAdmin(admin.ModelAdmin):
          raw_id_fields = ["newspaper"]

  The `raw_id_fields` `Input` widget should contain a primary key if the field is a `ForeignKey` or a comma separated list of values if the field is a `ManyToManyField`. The `raw_id_fields` widget shows a magnifying glass button next to the field which allows users to search for and select a value:

ModelAdmin.readonly_fields

  Secara awalan admin menunjukkan semua bidang sebagai dapat disunting. Bidang-bidang apapun di pilihan ini (yang harus berupa sebuah `list` atau `tuple`) akan menampilkan data dengan-adanya dan bukan-dapat disunting; mereka juga dikeluarkan dari `ModelForm` digunakan untuk membuat dan menyunting. catat bahwa ketika menentukan `ModelAdmin.fields` atau `ModelAdmin.fieldsets` bidang-bidang hanya-baca harus hadir untuk ditunjukkan (mereka diabaikan sebaliknya).

  Jika `readonly_fields` digunakan tanpa menentukan urutan jelas melalui `ModelAdmin.fields` atau `ModelAdmin.fieldsets` mereka akan ditambahkan setelah semua bidang dapat disunting.

  A read-only field can not only display data from a model's field, it can also display the output of a model's method or a method of the `ModelAdmin` class itself. This is very similar to the way `ModelAdmin.list_display` behaves. This provides a way to use the admin interface to provide feedback on the status of the objects being edited, for example:

      from django.contrib import admin
      from django.utils.html import format_html_join
      from django.utils.safestring import mark_safe

      class PersonAdmin(admin.ModelAdmin):
          readonly_fields = ["address_report"]

          # description functions like a model field's verbose_name
          @admin.display(description="Address")
          def address_report(self, instance):
              # assuming get_full_address() returns a list of strings
              # for each line of the address and you want to separate each
              # line by a linebreak
              return format_html_join(
                  mark_safe("<br>"),
                  "{}",
                  ((line,) for line in instance.get_full_address()),
              ) or mark_safe("<span class='errors'>I can't determine this address.</span>")

ModelAdmin.save_as

  Setel `save_as` untuk mengadakan sebuah fitur "save as new" pada formulir rubah admin.

  Biasanya, obyek-obyek mempunyai tiga pilihan simpan: "Save", "Save and continue editing", dan "Save and add another". Jika `save_as` adalah `True`, "Save and add another" akan diganti oleh sebuah tombol "Save as new" yang membuat sebuah obyek baru (dengan sebuah ID baru) daripada memperbaharui obyek yang ada.

  Secara awal, `save_as` disetel ke `False`.

ModelAdmin.save_as_continue

  Ketika `save_as=True`, awalan pengalihan setelah menyimpan obyek baru adalah merubah tampilan untuk obyek itu. Jika anda menyetel `save_as_continue=False`, pengalihan akan ke tampilan daftar rubah.

  Secara awal, `save_as_continue` disetel menjadi `False`.

ModelAdmin.save_on_top

  Setel `save_on_top` untuk menambah tombol simpan lintas atas dari formulir rubah admin anda.

  Biasanya, tombol simpan muncul hanya pada bawah dari formulir. Jika anda menyetel `save_on_top`, tombol-tombol akan muncul kedua pada atas dan bawah.

  Secara awal, `save_on_top` disetel ke `False`.

ModelAdmin.search_fields

  Setel `search_fields` untuk mengadakan sebah kotak pencarian pada halaman daftar rubah admin. Ini harus disetel ke sebuah daftar dari nama-nama bidang yang akan dicari kapanpun seseorang mengajukan permintaan pencarian di kotak teks itu.

  Bidang-bidang ini harus ada semacam bidang teks, seperti `CharField` atau `TextField`. Anda dapat juga melakukan pencarian terkait pada sebuah `ForeignKey` atau `ManyToManyField` catatan "follow" dengan API pencarian:

      search_fields = ["foreign_key__related_fieldname"]

  Sebagai contoh, jika anda mempunyai sebuah masukan blog dengan sebuah penulis, pengertian berikut akan mengadakan pencarian masukan blog berdasarkan alamat surel dari penulis.

      search_fields = ["user__email"]

  When somebody does a search in the admin search box, Django splits the search query into words and returns all objects that contain each of the words, case-insensitive (using the `icontains` lookup), where each word must be in at least one of `search_fields`. For example, if `search_fields` is set to `['first_name', 'last_name']` and a user searches for `john lennon`, Django will do the equivalent of this SQL `WHERE` clause:

      WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
      AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')

  The search query can contain quoted phrases with spaces. For example, if a user searches for `"john winston"` or `'john winston'`, Django will do the equivalent of this SQL `WHERE` clause:

      WHERE (first_name ILIKE '%john winston%' OR last_name ILIKE '%john winston%')

  Jika anda tidak ingin menggunakan `icontains` sebagai pencarian, anda dapat menggunakan pencarian apapun dengan menambahkan itu ke bidang. Sebagai contoh, anda dapat menggunakan `exact` dengan menyetel `search_field` menjadi `['first_name__exact']`.

  Beberapa jalan pintas (paling lama) untuk menentukan pencarian bidang juga tersedia. Anda dapat menambahkan sebuah bidang dalam `search_fields` dengan karakter berikut dan itu setara pada menambahkan `__` ke bidang:

  Awalan | Cari
  --- | ---
  ^ | `istartswith`
  = | `iexact`
  @ | `search`
  None | `icontains`

  Jika anda butuh menyesuaikan pencarian anda dapat menggunakan `ModelAdmin.get_search_results()` untuk menyediakan tambahan atau pengganti perilaku pencarian.

ModelAdmin.search_help_text

  Set `search_help_text` to specify a descriptive text for the search box which will be displayed below it.

ModelAdmin.show_full_result_count

  Setel `show_full_result_count` untuk mengendalikan apakah perhitungan penuh dari obyek harus ditampilkan pada halaman admin disaring (misalnya `99 hasil (jumlah 103)`). Jika pilihan ini disetel menjadi `False`, sebuah teks seperti `99 hasil (Tampilkan semua)` ditampilkan sebagai gantinya.

  Awalan dari `show_full_result_count=True` membangkitkan sebuah permintaan untuk melakukan perhitungan penuh pada tabel yang dapat mahal jika isi tabel mengandung sejumlah nomor dari baris.

ModelAdmin.sortable_by

  By default, the change list page allows sorting by all model fields (and callables that use the `ordering` argument to the `display()` decorator or have the `admin_order_field` attribute) specified in `list_display`.

  Jika anda ingin meniadakan pemilihan untuk beberapa kolom, setel `sortable_by` pada sebuah kumpulan (misalnya `list`, `tuple`, atau `set`) dari himpunan bagian `list_display` yang anda ingin menjadi dapat dipilih. Sebuah kumpulan kosong meniadakan pemilihan untuk semua kolom.

  Jika anda butuh menentukan daftar ini secara dinamis, terapkan metode `get_sortable_by()` sebagai gantinya.

ModelAdmin.view_on_site

  Setel `view_on_site` untuk mengendalikan apakah atau tidak ditampilkan tautan "View on site". Tautan ini harus membawa anda ke URL dimana anda dapat menampilkan obyek tersimpan.

  Nilai ini dapat berupa baik bendera boolean atau callable. Jika `True` (awalan), metode obyek `get_absolute_url()` akan digunakan untuk membangkitkan url.

  Jika model anda mempunyai metode `get_absolute_url()` tetapi anda tidak ingin tombol "View on site" muncul, anda hanya butuh mensetel `view_on_site` menjadi `False`:

      from django.contrib import admin

      class PersonAdmin(admin.ModelAdmin):
          view_on_site = False

  Di kasus itu adalah callable, itu menerima instance model sebagai parameter. Sebagi contoh:

      from django.contrib import admin
      from django.urls import reverse

      class PersonAdmin(admin.ModelAdmin):
          def view_on_site(self, obj):
              url = reverse("person-detail", kwargs={"slug": obj.slug})
              return "https://example.com" + url

#### Penyesuaian pilihan cetakan

The Menimpa cetakan admin section describes how to override or extend the default admin templates. Use the following options to override the default templates used by the `ModelAdmin` views:

ModelAdmin.add_form_template

  Jalur pada cetakan penyesuaian, digunakan oleh `add_view()`.

ModelAdmin.change_form_template

  Jalur untuk cetakan penyesuaian, digunakan oleh `change_view()`.

ModelAdmin.change_list_template

  Jalur pada cetakan penyesuaian, digunakan oleh `changelist_view()`.

ModelAdmin.delete_confirmation_template

  Jalur pada cetakan penyesuaian, digunakan oleh `delete_view()` untuk menampilkan halaman penegasan ketika menghapus satu atau lebih obyek.

ModelAdmin.delete_selected_confirmation_template

  Jalur pada cetakan penyesuaian, digunakan oleh tindakan `delete_selected` untuk memperlihatkan halaman penegasan ketika menghapus satu atau lebih obyek. Lihat actions documentation.

ModelAdmin.object_history_template

  Jalur pada cetakan penyesuaian, digunakan oleh `history_view()`.

ModelAdmin.popup_response_template

  Jalur pada cetakan penyesuaian, digunakan oleh `response_add()`, `response_change()`, dan `response_delete()`.

### Cara `ModelAdmin`

Peringatan

Ketika menimpa `ModelAdmin.save_model()` dan `ModelAdmin.delete_model()`, kode anda harus simpan/hapus obyek. Mereka tidak berarti untuk tujuan melarang, daripada mereka mengizinkan anda melakukan tindakan tambahan.

ModelAdmin.save_model(request, obj, form, change)

  Metode `save_model` memberikan `HttpRequest`, sebuah instance model, sebuah instance `ModelForm`, dan sebuah nilai boolean berdasarkan pada apakah itu sedang menambahkan atau merubah obyek. Menimpa metode ini mengizinkan melakukan tindakan pra- atau menempatkan-simpan. Memanggil `super().save_model()` untuk menyimpan obyek menggunakan `Model.save()`.

  Sebagai contoh untuk melampirkan `request.user` pada obyek sebelum menyimpannya:

      from django.contrib import admin

      class ArticleAdmin(admin.ModelAdmin):
          def save_model(self, request, obj, form, change):
              obj.user = request.user
              super().save_model(request, obj, form, change)

ModelAdmin.delete_model(request, obj)

  Metode `delete_model` diberikan `HttpRequest` dan sebuah instance model. Mengesampingkan metode ini mengizinkan melakukan tindakan menghapus pra- atau pasca-. Panggil `super().delete_model()` untuk menghapus obyek menggunakan `Model.delete()`.

ModelAdmin.delete_queryset(request, queryset)

  The `delete_queryset()` method is given the `HttpRequest` and a `QuerySet` of objects to be deleted. Override this method to customize the deletion process for the "delete selected objects" action.

ModelAdmin.save_formset(request, form, formset, change)

  Metode `save_formset` memberikan `HttpRequest`, instance `ModelForm` induk dan nilai boolean berdasarkan pada apakah itu sedang menambahkan atau merubah obyek induk.

  Sebagai contoh, untuk melampirkan `request.user` pada setiap instance model formset dirubah:

      class ArticleAdmin(admin.ModelAdmin):
          def save_formset(self, request, form, formset, change):
              instances = formset.save(commit=False)
              for obj in formset.deleted_objects:
                  obj.delete()
              for instance in instances:
                  instance.user = request.user
                  instance.save()
              formset.save_m2m()

  Lihat juga Saving objects in the formset.

Peringatan

All hooks that return a `ModelAdmin` property return the property itself rather than a copy of its value. Dynamically modifying the value can lead to surprising results.

Let's take `ModelAdmin.get_readonly_fields()` as an example:

    class PersonAdmin(admin.ModelAdmin):
        readonly_fields = ["name"]

        def get_readonly_fields(self, request, obj=None):
            readonly = super().get_readonly_fields(request, obj)
            if not request.user.is_superuser:
                readonly.append("age")  # Edits the class attribute.
            return readonly

This results in `readonly_fields` becoming `["name", "age", "age", ...]`, even for a superuser, as `"age"` is added each time non-superuser visits the page.

ModelAdmin.get_ordering(request)

  Metode `get_ordering` mengambil `request` sebagai parameter dan diharapkan mengembalikan sebuah `list` atau `tuple` untuk mengurutkan mirip pada atribut `ordering`. Sebagai contoh:

      class PersonAdmin(admin.ModelAdmin):
          def get_ordering(self, request):
              if request.user.is_superuser:
                  return ["name", "rank"]
              else:
                  return ["name"]

ModelAdmin.get_search_results(request, queryset, search_term)

  Metode `get_search_results` merubah daftar dari obyek-obyek diperlihatkan kedalam itu yang cocok istilah pencarian disediakan. Itu menerima permintaan, sebuah queryset yang memberlakukan penyaring saat ini, dan istilah pencarian disediakan-pengguna. Itu mengembalikan sebuah tuple mengandung sebuah queryset dirubah untuk menerapkan pencarian, dan sebuah boolean mengindikasikan jika hasil mungkin mengandung ganda.

  Pencarian penerapan awalan bidang-bidang bernama di `ModelAdmin.search_fields`.

  This method may be overridden with your own custom search method. For example, you might wish to search by an integer field, or use an external tool such as Solr or Haystack. You must establish if the queryset changes implemented by your search method may introduce duplicates into the results, and return `True` in the second element of the return value.

  Sebagai contoh, untuk mencari `name` dan `age`, anda dapat menggunakan:

      class PersonAdmin(admin.ModelAdmin):
          list_display = ["name", "age"]
          search_fields = ["name"]

          def get_search_results(self, request, queryset, search_term):
              queryset, may_have_duplicates = super().get_search_results(
                  request,
                  queryset,
                  search_term,
              )
              try:
                  search_term_as_int = int(search_term)
              except ValueError:
                  pass
              else:
                  queryset |= self.model.objects.filter(age=search_term_as_int)
              return queryset, may_have_duplicates

  Penerapan ini lebih efesien dari `search_fields = ('name', '=age')` yang menghasilkan dalam sebuah perbandingan string untuk bidang numerik, sebagai contoh `... OR UPPER("polls_choice"."votes"::text) = UPPER('4')` pada PostgreSQL.

ModelAdmin.save_related(request, form, formsets, change)

  Metode `save_related` memberikan `HttpRequest`, sebuah instance `ModelForm` induk, daftar dari formset berderet dan sebuah nilai boolean berdasarkan pada apakah induk sedang ditambahkan atau dirubah. Disini anda dapat melakukan tindakan pra- atau pasca- untuk obyek-obyek terkait ke induk. Catat bahwa pada titik ini obyek induk dan formulirnya telah disimpan.

ModelAdmin.get_autocomplete_fields(request)

  Metode `get_autocomplete_fields()` memberikan `HttpRequest` dan diharapkan mengembalikan sebuah `list` atau `tuple` dari nama bidang yang akan ditampilkan dengan sebuah widget pelengkapan otomatis seperti digambarkan diatas dalam bagian `ModelAdmin.autocomplete_fields`.

ModelAdmin.get_readonly_fields(request, obj=None)

  Metode `get_readonly_fields` memberikan `HttpRequest` dan `obj` sedang disunting atau `None` pada sebuah formulir tambah) dan diharapkan mengembalikan sebuah `list` (atau `tuple` dari nama-nama bidang yang akan diperlihatkan sebagai hanya-baca, seperti digambarkan diatas di bagian `ModelAdmin.readonly_fields`.

ModelAdmin.get_prepopulated_fields(request, obj=None)

  Metode `get_prepopulated_fields` memberikan `HttpRequest` dan `obj` sedang disunting (atau `None` pada sebuah formulir tambah) dan diharapkan untuk mengembalikan sebuah `dictionary`, seperti digambarkan diatas di bagian `ModelAdmin.prepopulated_fields`.

ModelAdmin.get_list_display(request)

  Metode `get_list_display` memberikan `HttpRequest` dan diharapkan mengembalikan sebuah `list` atau `tuple` dari nama-nama bidang yang akan diperlihatkan pada tampilan daftar rubah seperti digambarkan diatas di bagian `ModelAdmin.list_display`.

ModelAdmin.get_list_display_links(request, list_display)

  Metode `get_list_display_links` memberikan `HttpRequest` dan `list` atau `tuple` dikembalikan oleh `ModelAdmin.get_list_display()`. Itu diharapkan mengembalikan antara `None` atau sebuah `list` atau `tuple` dari nama-nama bidang pada daftar rubah yang akan ditautkan ke tampilan rubah, seperti digambarkan di bagian `ModelAdmin.list_display_links`.

ModelAdmin.get_exclude(request, obj=None)

  Metode `get_exclude` memberikan `HttpRequest` dan `obj` sedang disunting (atau `None` pada sebuah formulir tambah) dan diharapkan untuk mengembalikan sebuah daftar dari bidang-bidang, seperti digambarkan diatas di bagian `ModelAdmin.exclude`.

ModelAdmin.get_fields(request, obj=None)

  Metode `get_fields` memberikan `HttpRequest` dan `obj` sedang disunting (atau `None` pada sebuah formulir tambah) dan diharapkan untuk mengembalikan sebuah daftar dari bidang-bidang, seperti digambarkan diatas di bagian `ModelAdmin.fields`.

ModelAdmin.get_fieldsets(request, obj=None)

  The `get_fieldsets` method is given the `HttpRequest` and the `obj` being edited (or `None` on an add form) and is expected to return a list of 2-tuples, in which each 2-tuple represents a `<fieldset>` on the admin form page, as described above in the `ModelAdmin.fieldsets` section.

ModelAdmin.get_list_filter(request)

  Metode `get_list_filter` memberikan `HttpRequest` dan diharapkan mengembalikan jenis yang sama dari urutan jenis seperti untuk atribut `list_filter`.

ModelAdmin.get_list_select_related(request)

  Metode `get_list_select_related` memberikan `HttpRequest` dan harus mengembalikan sebuah boolean atau daftar seperti `ModelAdmin.list_select_related` lakukan.

ModelAdmin.get_search_fields(request)

  Metode `get_search_fields` memberikan `HttpRequest` dan diharapkan mengembalikan jenis yang sama dari urutan jenis seperti untuk atribut `search_fields`.

ModelAdmin.get_sortable_by(request)

  Metode `get_sortable_by()` melewatkan `HttpRequest` dan dan diharapapkan mengembalikan kumpulan (misalnya `list`, `tuple`, atau `set`) dari nama-nama bidang yang akan diurutkan dalam halaman daftar rubah.

  Penerapan awalnya mengambalikan `sortable_by` jika disetel, sebaliknya itu menunda ke `get_list_display()`.

  Sebagai contoh, untuk mencegah satu atau lebih kolom dari menjadi dapat diurutkan:

      class PersonAdmin(admin.ModelAdmin):
          def get_sortable_by(self, request):
              return {*self.get_list_display(request)} - {"rank"}

ModelAdmin.get_inline_instances(request, obj=None)

  Metode `get_inline_instances` memberikan `HttpRequest` dan `obj` sedang dirubah (atau `None` pada formulir tambah) dan diharapkan mengembalikan sebuah `list` atau `tuple` dari obyek `InlineModelAdmin`, seperti digambarkan dibawah dalam bagian `InlineModelAdmin`. Sebagai contoh, berikut akan mengembalikan dibarisan tanpa penyaringan awalan berdasarkan pada perizinan tambah, rubah, hapus, dan menampilkan:

      class MyModelAdmin(admin.ModelAdmin):
          inlines = [MyInline]

          def get_inline_instances(self, request, obj=None):
              return [inline(self.model, self.admin_site) for inline in self.inlines]

  Jika anda mengutamakan metode ini, pastikan bahwa berderet dikembalikan adalah instance dari kelas-kelas ditentukan di `inlines` atau anda mungkin menghadapi kesalahan "Bad Request" ketika menambahkan obyek-obyek terkait.

ModelAdmin.get_inlines(request, obj)

  The `get_inlines` method is given the `HttpRequest` and the `obj` being edited (or `None` on an add form) and is expected to return an iterable of inlines. You can override this method to dynamically add inlines based on the request or model instance instead of specifying them in `ModelAdmin.inlines`.

ModelAdmin.get_urls()

  The `get_urls` method on a `ModelAdmin` returns the URLs to be used for that ModelAdmin in the same way as a URLconf. Therefore you can extend them as documented in Pengirim URL, using the `AdminSite.admin_view()` wrapper on your views:

      from django.contrib import admin
      from django.template.response import TemplateResponse
      from django.urls import path

      class MyModelAdmin(admin.ModelAdmin):
          def get_urls(self):
              urls = super().get_urls()
              my_urls = [path("my_view/", self.admin_site.admin_view(self.my_view))]
              return my_urls + urls

          def my_view(self, request):
              # ...
              context = dict(
                  # Include common variables for rendering the admin template.
                  self.admin_site.each_context(request),
                  # Anything else you want in the context...
                  key=value,
              )
              return TemplateResponse(request, "sometemplate.html", context)

  Jika anda ingin menggunakan tata letak admin, perpanjang dari `admin/base_site.html`:

      {% extends "admin/base_site.html" %}
      {% block content %}
      ...
      {% endblock %}

  Catatan

  Notice how the `self.my_view` function is wrapped in `self.admin_site.admin_view`. This is important, since it ensures two things:

  1. Permission checks are run, ensuring only active staff users can access the view.

  2. The `django.views.decorators.cache.never_cache()` decorator is applied to prevent caching, ensuring the returned information is up-to-date.

  Catatan

  Perhatikan bahwa pola penyesuaian disertakan sebelum URL admin biasa: pola URL admin adalah sangat membolehkan dan akan cocok hampir apapun, jadi anda akan biasanya ingin menambahkan URL penyesuaian anda pada satu di siap-pakai.

  Di contoj ini, `my_view` akan diakses pada `/admin/myapp/mymodel/my_view/` (menganggap URL admin disertakan pada `/admin/`.)

  Jika halaman adalah cacheable, tetapi anda masih ingin pemeriksaan perizinan dilakukan, anda dapat melewatkan sebuah argumen `cacheable=True` pada `AdminSite.admin_view()`:

      path("my_view/", self.admin_site.admin_view(self.my_view, cacheable=True))

  Tampilan `ModelAdmin` mempunyai atribut `model_admin`. Selain tampilan `AdminSite` mempunyai atribut `admin_site`.

ModelAdmin.get_form(request, obj=None, **kwargs)

  Mengembalikan sebuah kelas `ModelForm` untuk digunakan di tampilan tambah dan rubah admin, lihat `add_view()` dan `change_view()`.

  Penerapan dasar menggunakan `modelform_factory()` pada subkelas `form`, dirubah oleh atribut seperti `fields` dan `exclude`. Jadi, sebagai contoh, jika anda ingin menawarkan tambahan bidang-bidang le superuser, anda dapat menukar formulir dasar berbeda seperi begitu:

      class MyModelAdmin(admin.ModelAdmin):
          def get_form(self, request, obj=None, **kwargs):
              if request.user.is_superuser:
                  kwargs["form"] = MySuperuserForm
              return super().get_form(request, obj, **kwargs)

  Anda mungkin juga mengembalikan kelas `ModelForm` penyesuaian langsung.

ModelAdmin.get_formsets_with_inlines(request, obj=None)

  Menghasilkan (`FormSet`, `InlineModelAdmin`) pasangan untuk digunakan di tampilan tambah dan rubah admin.

  Sebagai contoh jika anda ingin memperlihatkan hanya berderet tertentu di tampilan rubah, anda dapat menimpa `get_formsets_with_inlines` sebagai berikut:

      class MyModelAdmin(admin.ModelAdmin):
          inlines = [MyInline, SomeOtherInline]

          def get_formsets_with_inlines(self, request, obj=None):
              for inline in self.get_inline_instances(request, obj):
                  # hide MyInline in the add view
                  if not isinstance(inline, MyInline) or obj is not None:
                      yield inline.get_formset(request, obj), inline

ModelAdmin.formfield_for_foreignkey(db_field, request, **kwargs)

  Metode `formfield_for_foreignkey` pada sebuah `ModelAdmin` mengizinkan anda menimpa formfield awalan untuk bidang foreign key. Sebagai contoh, untuk mengembalikan bagian dari obyek-obyek untuk bidang foreign key ini berdasarkan pada pengguna:

      class MyModelAdmin(admin.ModelAdmin):
          def formfield_for_foreignkey(self, db_field, request, **kwargs):
              if db_field.name == "car":
                  kwargs["queryset"] = Car.objects.filter(owner=request.user)
              return super().formfield_for_foreignkey(db_field, request, **kwargs)

  Penggunaan ini instance `HttpRequest` untuk menyaring bidang foreign key `Car` ke hanya meperlihatkan mobil dimiliki oleh instance `User`.

  For more complex filters, you can use `ModelForm.__init__()` method to filter based on an `instance` of your model (see Bidang-bidang yang menangani hubungan). For example:

      class CountryAdminForm(forms.ModelForm):
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              self.fields["capital"].queryset = self.instance.cities.all()

      class CountryAdmin(admin.ModelAdmin):
          form = CountryAdminForm

ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)

  Seperti metode `formfield_for_foreignkey`, metode `formfield_for_manytomany` dapat dikesampingkan untuk merubah formfield awalan untuk bidang many to many. Sebagai contoh, jika seorang pemilik dapat memiliki banyak mobil dan mobil dapat dimiliki banyak pemilik -- hubungan many to many -- anda dapat penyaring bidang foreign key `Car` pada hanya memperlihatkan pemilik mobil berdasarkan `User`:

      class MyModelAdmin(admin.ModelAdmin):
          def formfield_for_manytomany(self, db_field, request, **kwargs):
              if db_field.name == "cars":
                  kwargs["queryset"] = Car.objects.filter(owner=request.user)
              return super().formfield_for_manytomany(db_field, request, **kwargs)

ModelAdmin.formfield_for_choice_field(db_field, request, **kwargs)

  Seperti metode `formfield_for_foreignkey` dan `formfield_for_manytomany`, metode `formfield_for_choice_field` dapat ditimpa untuk merubah formfield awalan untuk sebuah bidang yang telah menyatakan pilihan. Sebagai contoh, jika pilihan tersedia pada superuser harus berbeda dari tersebut tersedia pada staf biasa, anda dapat meneruskan sebagai berikut:

      class MyModelAdmin(admin.ModelAdmin):
          def formfield_for_choice_field(self, db_field, request, **kwargs):
              if db_field.name == "status":
                  kwargs["choices"] = [
                      ("accepted", "Accepted"),
                      ("denied", "Denied"),
                  ]
                  if request.user.is_superuser:
                      kwargs["choices"].append(("ready", "Ready for deployment"))
              return super().formfield_for_choice_field(db_field, request, **kwargs)

  `choices` limitations

  Setiap kumpulan atribut `choices` pada formfield akan dibatasi pada hanya bidang formulir. Jika bidang berhubungan pada model mempunyai kumpulan pilihan, pilihan-pilihan akan disediakan pada formulir harus berupa subkumpulan sah dari pilihan-pilihan tersebut, sebaliknya pengajuan formulir akan gagal dengan sebuah `ValidationError` ketika model itu sendiri disahkan sebelum disimpan.

ModelAdmin.get_changelist(request, **kwargs)

  Mengembalikan kelas `Changelist` untuk digunakan untuk pendaftaran. Secara awalan, `django.contrib.admin.views.main.ChangeList` digunakan. Dengan mewarisi kelas ini anda dapat merubah perilaku dari pendaftaran.

ModelAdmin.get_changelist_form(request, **kwargs)

  Mengembalikan sebuah kelas `ModelForm` untuk digunakan di `Formset` pada halaman daftar rubah. Untuk menggunakan formulir penyesuaian, sebagai contoh:

      from django import forms

      class MyForm(forms.ModelForm):
          pass

      class MyModelAdmin(admin.ModelAdmin):
          def get_changelist_form(self, request, **kwargs):
              return MyForm

  Omit the `Meta.model` attribute

  Jika anda menentukan atribut `Meta.model` pada sebuah `ModelForm`, anda harus juga menentukan atribut `Meta.fields` (atau atribut `Meta.exclude`). Bagaimanapun, `ModelAdmin` mengabaikan nilai ini, menimpa itu dengan atribut `ModelAdmin.list_editable`. Pemecahan paling mudah adalah menghilangkan atribut `Meta.model`, sejak `ModelAdmin` akan menyediakan model benar untuk digunakan.

ModelAdmin.get_changelist_formset(request, **kwargs)

  Mengembalikan sebuah kelas ModelFormSet untuk digunakan pada halaman daftar rubah jika `list_editable` digunakan. Untuk menggunakan formset penyesuaian, sebagai contoh:

      from django.forms import BaseModelFormSet

      class MyAdminFormSet(BaseModelFormSet):
          pass

      class MyModelAdmin(admin.ModelAdmin):
          def get_changelist_formset(self, request, **kwargs):
              kwargs["formset"] = MyAdminFormSet
              return super().get_changelist_formset(request, **kwargs)

ModelAdmin.lookup_allowed(lookup, value, request)

  Obyek-obyek dalam halaman daftar rubah dapat disaring dengan pencarian dari string permintaan URL. Ini adalah bagaimana `list_filter` bekerja, sebagai contoh. Pencarian mirip pada apa yang digunakan dalam `QuerySet.filter()` (misalnya `user__email=user@example.com`). Sejak pencarian dalam string permintaan dapat diubah oleh pengguna, mereka harus dibersihkan untuk mencegah pembukaan data tidak berhak.

  The `lookup_allowed()` method is given a lookup path from the query string (e.g. `'user__email'`), the corresponding value (e.g. `'user@example.com'`), and the request, and returns a boolean indicating whether filtering the changelist's `QuerySet` using the parameters is permitted. If `lookup_allowed()` returns `False`, `DisallowedModelAdminLookup` (subclass of `SuspiciousOperation`) is raised.

  Secara awalan, `lookup_allowed()` mengizinkan akses pada bidang lokal model, jalur-jalur bidang digunakan dalam `list_filter` (tetapi bukan jalur dari `get_list_filter()`), dan pencarian dibutuhkan untuk `limit_choices_to` pada fungsi dengan benar dalam `raw_id_fields`.

  Menimpa metode ini untuk menyesuaikan pencarian diizinkan untuk subkelas `ModelAdmin` anda.

ModelAdmin.has_view_permission(request, obj=None)

  Harus mengembalikan `True` jika menampilkan `obj` diizinkan, `False` sebaliknya. Jika obj adalah `None`, harus mengembalikan `True` atau `False` untuk menunjukkan apakah menampilkan obyek dari jenis ini diizinkan secara umum (misalnya, `False` akan diterjemahkan sebagai artian bahwa pengguna saat ini tidak diizinkan menampilkan obyek apapun dai jenis ini).

  Penerapan awalan mengembalikan `True` jika pengguna mempunyai baik perizinan "change" atau "view".

ModelAdmin.has_add_permission(request)

  Harus mengembalikan `True` jika menambahkan sebuah obyek diizinkan, `False` sebaliknya.

ModelAdmin.has_change_permission(request, obj=None)

  Harus mengembalikan `True` jika penyuntingan `obj` diizinkan, `False` sebaliknya. Jika `obj` adalah `None`, harus mengembalikan `True` atau `False` untuk menunjukkan apakah penyuntingan dari obyek jenis ini diizinkan secara umum (misalnya, `False` akan diterjemahkan sesuai artian bahwa pengguna saat ini tidak diizinkan untuk menyunting obyek apapun dari jenis ini).

ModelAdmin.has_delete_permission(request, obj=None)

  Harus mengembalikan `True` jika penghapusan `obj` diizinkan, `False` sebaliknya. Jika `obj` adalah `None`, harus mengembalikan `True` atau `False` untuk menunjukkan apakah penghapusan obyek jenis ini diizinkan secara umum (misalnya, `False` jika diterjemahkan sesuai artian bahwa pengguna saat ini tidak diizinkan menghapus obyek apapun dari jenis ini).

ModelAdmin.has_module_permission(request)

  Harus mengembalikan `True` jika menampilkan modul pada halaman index admin dan mengakses halaman index admin diizinkan, `False` sebaliknya. Menggunakan `User.has_module_perms()` secara awalan. menimpa itu tidak membatasi akses pada tampilan melihat, tambah, rubah, atau hapus, `has_view_permission()`, `has_add_permission()`, `has_change_permission()`, dan `has_delete_permission()` harus digunakan untuk itu.

ModelAdmin.get_queryset(request)

  Metode `get_queryset` pada sebuah `ModelAdmin` mengembalikan sebuah `QuerySet` dari semua instance model yang dapat disunting oleh situs admin. Satu kasus penggunaan dari mengutamakan metode ini adalah menunjukkan obyek-obyek dimiliki oleh pengguna masuk:

      class MyModelAdmin(admin.ModelAdmin):
          def get_queryset(self, request):
              qs = super().get_queryset(request)
              if request.user.is_superuser:
                  return qs
              return qs.filter(author=request.user)

ModelAdmin.message_user(request, message, level=messages.INFO, extra_tags='', fail_silently=False)

  Sends a message to the user using the `django.contrib.messages` backend. See the custom ModelAdmin example.

  Argumen kata kunci mengizinkan anda merubah tingkatan pesan, menambah tambahan etiket CSS, atau gagal secara diam jika kerangka kerja `contrib.messages` tidak dipasang. Argumen kata kunci ini cocok dengan untuk `django.contrib.messages.add_message()`, lihat dokumentasi fungsi itu untuk lebih rinci. Satu perbedaan adalah bahwa tingkatan mungkin dilewatkan sebagai label string sebagai tambahan pada integer/ketetapan.

ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)

  Mengembalikan sebuah instance dari penomor digunakan untuk tampilan ini. Secara awalan, instasiasi sebuah instance dari `paginator`.

ModelAdmin.response_add(request, obj, post_url_continue=None)

  Menentukan tahap the `HttpResponse` for the `add_view()`.

  `response_add` dipanggil setelah formulir admin diajukan dan hanya setelah obyek dan semua instances terkait telah dibuat dan disimpan. Anda dapat menimpanya untuk merubah perilaku awalan setelah obyek telah dibuat.

ModelAdmin.response_change(request, obj)

  Menentukan tahap `HttpResponse` for the `change_view()`.

  `response_change` dipanggil setelah formulir admin diajukan dan hanya setelah obyek dan semua instances terkait telah disimpan. Anda dapat menimpanya untuk merubah perilaku awalan setelah obyek telah dirubah.

ModelAdmin.response_delete(request, obj_display, obj_id)

  Menentukan `HttpResponse` untuk tahap `delete_view()`.

  `response_delete` dipanggil setelah obyek telah dihapus. Anda dapat menimpa ini untuk merubah kebiasaan awal setelah obyek telah dihapus.

  `obj_display` adalah sebuah string dengan nama dari obyek terhapus.

  `obj_id` adalah penciri serial digunakan untuk mengambil obyek untuk dihapus.

ModelAdmin.get_formset_kwargs(request, obj, inline, prefix)

  A hook for customizing the keyword arguments passed to the constructor of a formset. For example, to pass `request` to formset forms:

      class MyModelAdmin(admin.ModelAdmin):
          def get_formset_kwargs(self, request, obj, inline, prefix):
              return {
                  **super().get_formset_kwargs(request, obj, inline, prefix),
                  "form_kwargs": {"request": request},
              }

  You can also use it to set `initial` for formset forms.

ModelAdmin.get_changeform_initial_data(request)

  Sebuah kaitan untuk data inisial pada formulir rubah admin. Secara awalan, bidang-bidang diberikan nilai-nilai inisial dari parameter `GET`. Sebagai contoh, `?name=initial_value` akan menyetel nilai inisial bidang `name` menjadi `initial_value`.

  Metode ini harus mengembalikan sebuah kamus di formulir `{'fieldname': 'fieldval'}`:

      def get_changeform_initial_data(self, request):
          return {"name": "custom_initial_value"}

ModelAdmin.get_deleted_objects(objs, request)

  A hook for customizing the deletion process of the `delete_view()` and the "delete selected" action.

  Argumen `objs` adalah perulangan sama dari obyek (`QuerySet` atau list dari instance model) untuk dihapus, dan `request` adalah `HttpRequest`.

  Metode ini harus mengembalikan 4-tuple dari `(deleted_objects, model_count, perms_needed, protected)`.

  `deleted_objects` list dari strings mewakili semua obyek yang akan dihapus. Jika ada obyek terkait untuk dihapus, list adalah bersarang dan menyertakan obyek terkait tersebut. List dibentuk dalam cetakan menggunakan penyaring `unordered_list`.

  `model_count` adalah sebuah pemetaan dictionary setiap `verbose_name_plural` model ke sejumalh obyek yang akan dihapus.

  `perms_needed` adalah kumpulan dari `verbose_name` dari model yang pengguna tidak mempunyai perizinan untuk hapus.

  `protected` adalah daftar dari string mewakili semua obyek-obyek terkait terlindungi yang tidak dapat dihapus. Daftar ditampilkan dalam cetakan.

#### Cara lain

ModelAdmin.add_view(request, form_url='', extra_context=None)

  Tampilan Django untuk halaman tambahan instance model. Lihat catatan dibawah.

ModelAdmin.change_view(request, object_id, form_url='', extra_context=None)

  Tampilan Django untuk halaman suntingan instance model. Lihat catatan dibawah.

ModelAdmin.changelist_view(request, extra_context=None)

  Tampilan Django untuk halaman daftar rubah/tindakan instance model. Lihat catatan dibawah.

ModelAdmin.delete_view(request, object_id, extra_context=None)

  Tampilan Django untuk halaman penegasan penghapusn instance model. Lihat catatan dibawah.

ModelAdmin.history_view(request, object_id, extra_context=None)

  Tampilan Django untuk halaman yang menampilan riwayat perubahan untuk instance model diberikan.

Tidak seperti jenis-kait metode `ModelAdmin` dirinci di bagian sebelumnya, lima metode ini yang pada kenyataannya dirancang untuk dipanggil sebagai tampilan Django dari URL aplikasi admin mengirim penangan untuk membangun halaman-halaman yang berhubungan dengan tindakan CRUD instance-instance model. Sebagai sebuah hasil, slengkapnya mengutamakan metode ini akan secara signifikan merubah perilaku admin aplikasi admin.

Satu alasan umum untuk mengutamakan metode ini adalah menambah data konteks yang disediakan ke cetakan yang membangun tampilan. Di contoh berikut, tamppilan rubah ditimpa sehingga cetakan dibangun menyediakan beberapa data pemetaan tambahan yang tidak akan sebaliknya menjadi tersedia:

    class MyModelAdmin(admin.ModelAdmin):
        # A template for a very customized change view:
        change_form_template = "admin/myapp/extras/openstreetmap_change_form.html"

        def get_osm_info(self):
            # ...
            pass

        def change_view(self, request, object_id, form_url="", extra_context=None):
            extra_context = extra_context or {}
            extra_context["osm_data"] = self.get_osm_info()
            return super().change_view(
                request,
                object_id,
                form_url,
                extra_context=extra_context,
            )

Tampilan ini mengembalikan instance `TemplateResponse` yang mengizinkan anda dengan mudah menyesuaikan data tanggapan sebelum membangun. Untuk rincian lebih, lihat TemplateResponse documentation.

### Pengertian aset `ModelAdmin`

Ada waktu dimana anda akan menambahkan sedikit CSS dan/atay JavaScript pada tampilan tambah/rubah. Ini dapat dicapai dengan menggunakan kelas `Media` sebelah dalam pada `ModelAdmin` anda:

    class ArticleAdmin(admin.ModelAdmin):
        class Media:
            css = {
                "all": ["my_styles.css"],
            }
            js = ["my_code.js"]

staticfiles app menambahkan `STATIC_URL` (atau `MEDIA_URL` jika `STATIC_URL` adalah `None`) pada jalur aset apapun. Peraturan sama berlaku seperti regular asset definitions on forms.

#### jQuery

JavaScript admin Django memanfaatkan pustaka jQuery

To avoid conflicts with user-supplied scripts or libraries, Django's jQuery (version 3.7.1) is namespaced as `django.jQuery`. If you want to use jQuery in your own admin JavaScript without including a second copy, you can use the `django.jQuery` object on changelist and add/edit views. Also, your own admin forms or widgets depending on `django.jQuery` must specify `js=['admin/js/jquery.init.js', …]` when declaring form media assets.

Kelas `ModelAdmin` membutuhkan jQuery secara awalan, jadi tidak butuh menambahkan jQuery ke daftar `ModelAdmin` anda dari sumber daya media meskipun anda mempunyai kebutuhan khusus. Sebagai contoh, jika anda membutuhkan pustaka jQuery menjadi di namespace global (sebagai contoh ketika menggunakan plugin jQuery pihak-ketiga) atau jika anda butuh versi terbaru dari jQuery, anda akan harus menyertakan salinan anda sendiri.

Django menyediakan kedua versi tidak dipadatkan dan 'dikecilkan' dari jQuery, sebagai masing-masing `jquery.js` dan `jquery.min.js`.

`ModelAdmin` dan `InlineModelAdmin` mempunyai sebuah sifat `media` yang mengembalikan sebuah daftar dari obyek `Media` yang menyimpan jalur pada berkas-berkas JavaScript untuk formulir dan/atau formset. Jika `DEBUG` adalah `True` itu akan mengembalikan versi tidak terpampat dari beragam berkas-berkas JavaScript, termasuk `jquery.js`; jika tidak, itu akan mengembalikan versi 'minified'.

### Menambahkan pengesahan penyesuaian pada admin

You can also add custom validation of data in the admin. The automatic admin interface reuses `django.forms`, and the `ModelAdmin` class gives you the ability to define your own form:

    class ArticleAdmin(admin.ModelAdmin):
        form = MyArticleAdminForm

`MyArticleAdminForm` dapat ditentukan dimanapun selama anda mengimpor ketika diperlukan. Sekarang dalam formulir anda anda dapat menambah penyesuaian pengesahan milik anda sendiri untuk bidang apapun:

    class MyArticleAdminForm(forms.ModelForm):
        def clean_name(self):
            # do something that validates your data
            return self.cleaned_data["name"]

Itu adalah penting anda menggunakan sebuah `ModelForm` disini sebaliknya hal-hal dapat rusak. Lihat dokuementasi forms pada custom validation dan, lebih khusus, model form validation notes untuk informasi lebih.

## Obyek `InlineModelAdmin`

class InlineModelAdmin

class TabularInline

class StackedInline

  Antarmuka admin mempunyai kemampuan menyunting model-model pada halaman sama sebagai model induk. Ini adalah dipanggil berderet. Andaikan anda mempunyai kedua model ini:

      from django.db import models

      class Author(models.Model):
          name = models.CharField(max_length=100)

      class Book(models.Model):
          author = models.ForeignKey(Author, on_delete=models.CASCADE)
          title = models.CharField(max_length=100)

  Anda dapat menyunting buku-buku ditulis oleh seorang penulis pada halaman penulis. Anda tambah berderet pada sebuah model dengan menentukan mereka di sebuah `ModelAdmin.inlines`:

      from django.contrib import admin
      from myapp.models import Author, Book

      class BookInline(admin.TabularInline):
          model = Book

      class AuthorAdmin(admin.ModelAdmin):
          inlines = [
              BookInline,
          ]

      admin.site.register(Author, AuthorAdmin)

  Django menyediakan dua subkelas dari `InlineModelAdmin` dan mereka adalah:

  - `TabularInline`

  - `StackedInline`

  Perbedaan diantara kedua ini adalah hanya cetakan digunakan untuk membangun mereka.

### Pilihan `InlineModelAdmin`

`InlineModelAdmin` berbagi banyak dari fitur-fitur sama seperti `ModelAdmin`, dan menambahkan beberapa dari miliknya (fitur-fitur dibagi sebenarnya ditentukan di superkelas `BaseModelAdmin`). Fitur-fitur dibagi adalah:

- `form`

- `fieldsets`

- `fields`

- `formfield_overrides`

- `exclude`

- `filter_horizontal`

- `filter_vertical`

- `ordering`

- `prepopulated_fields`

- `get_fieldsets()`

- `get_queryset()`

- `radio_fields`

- `readonly_fields`

- `raw_id_fields`

- `formfield_for_choice_field()`

- `formfield_for_foreignkey()`

- `formfield_for_manytomany()`

- `has_module_permission()`

Kelas `InlineModelAdmin` menambah atau menyesuaikan:

InlineModelAdmin.model

  Model yang di berderet sedang menggunakan. Ini adalah diwajibkan.

InlineModelAdmin.fk_name

  Nama dari foreign key pada model. Di kebanyakan kasus ini akan ditangani dengan otomatis, tetapi `fk_name` harus ditentukan secara jelas jika ada lebih dari satu foreign key pada model induk yang sama.

InlineModelAdmin.formset

  Ini awalan pada `BaseInlineFormSet`. Menggunakan formset anda sendiri dapat memberikan anda banyak kemungkinan dari penyesuaian. Berderet adalah dibangun sekitar model formsets.

InlineModelAdmin.form

  NIlai untuk awalan `form` pada `ModelForm`. Ini adalah apa yang dilewatkan melalui `inlineformset_factory()` ketika membuat formset untuk berderet ini.

Peringatan

Ketika menulis pengesahan penyesuaian untuk formulir `InlineModelAdmin`, waspada dari menulis pengesahan yang bergantung pada fitur-fitur dari model induk. Jika model induk gagal mensahkan, itu mungkin ditinggal di keadaan yang tidak konsisten seperti digambarkan di peringatan di Pengesahan pada sebuah ModelForm.

InlineModelAdmin.classes

  A list or tuple containing extra CSS classes to apply to the fieldset that is rendered for the inlines. Defaults to `None`. As with classes configured in `fieldsets`, inlines with a `collapse` class will be initially collapsed using an expandable widget.

InlineModelAdmin.extra

  This controls the number of extra forms the formset will display in addition to the initial forms. Defaults to 3. See the formsets documentation for more information.

  Untuk pengguna dengan peramban diadakan-JavaScript, sebuah tautan "Add another" disediakan untuk mengadakan nomor apapun dari berderet tambahan untuk ditambahkan ke itu yang disediakan sebagai sebuah hasil dari argumen `extra`.

  Tautan dinamis tidak akan muncul jika sejumlah dari formulir diperlihatkan saat ini melebihi `max_num`, atau jika pengguna tidak mempunyai JavaScript diadakan.

  `InlineModelAdmin.get_extra()` juga mengizinkan anda menyesuaikan sejumlah formulir tambahan.

InlineModelAdmin.max_num

  Ini mengendalikan jumlah minimal dari formulir untuk menunjukkan di berderet. Ini tidak secara langsung menghubungankan ke sejumlah dari obyek, tetapi dapat jika nilai cukup kecil. Lihat Membatasi angka dari obyek dapat di sunting untuk informasi lebih.

  `InlineModelAdmin.get_max_num()` juga mengizinkan anda menyesuaikan nomor maksimal dari formulir tambahan.

InlineModelAdmin.min_num

  Ini mengendalikan jumlah minimal dari formulir untuk menunjukkan dalam deretan. Lihat `modelformset_factory()` untuk informasi lebih.

  `InlineModelAdmin.get_min_num()` juga mengizinkan anda menyesuaikan nomor minimal dari formulir ditampilkan.

InlineModelAdmin.raw_id_fields

  Secara awalan, admin Django menggunakan antarmuka kotak-pilih (<select>) untuk bidang-bidang adalah `ForeignKey`. Terkadang anda tidak ingin mendatangkan atas dari memiliki untuk memilih semua instance terkait untuk memperlihatkan di drop-down.

  `raw_id_fields` adalah sebuah daftar dari bidang anda ingin rubah menjadi widget `input` untuk antara sebuah `ForeignKey` atau `ManyToManyField`:

      class BookInline(admin.TabularInline):
          model = Book
          raw_id_fields = ["pages"]

InlineModelAdmin.template

  Cetakan digunakan untuk membangun berderet pada halaman.

InlineModelAdmin.verbose_name

  An override to the `verbose_name` from the model's inner `Meta` class.

InlineModelAdmin.verbose_name_plural

  An override to the `verbose_name_plural` from the model's inner `Meta` class. If this isn't given and the `InlineModelAdmin.verbose_name` is defined, Django will use `InlineModelAdmin.verbose_name` + `'s'`.

InlineModelAdmin.can_delete

  Menentukan apakah atau tidak obyek berderet dapat dihapus di berderet. Awalan menjadi `True`.

InlineModelAdmin.show_change_link

  Menentukan apakah atau tidak obyek berderet dapat dirubah di admin mempunyai sebuah tautan ke formulir rubah. Awalan menjadi `False`.

InlineModelAdmin.get_formset(request, obj=None, **kwargs)

  Returns a `BaseInlineFormSet` class for use in admin add/change views. `obj` is the parent object being edited or `None` when adding a new parent. See the example for `ModelAdmin.get_formsets_with_inlines`.

InlineModelAdmin.get_extra(request, obj=None, **kwargs)

  Mengembalikan sejumlah formulir berderet tambahan untuk digunakan. Secara awalan, mengembalikan atribut `InlineModelAdmin.extra`

  Timpa metode ini untuk secara program menentukan jumlah dari formulir berderet tambahan. Sebagai contoh, ini mungkin berdasarkan pada instance model (dilewatkan sebagai argumen kata kunci `obj`):

      class BinaryTreeAdmin(admin.TabularInline):
          model = BinaryTree

          def get_extra(self, request, obj=None, **kwargs):
              extra = 2
              if obj:
                  return extra - obj.binarytree_set.count()
              return extra

InlineModelAdmin.get_max_num(request, obj=None, **kwargs)

  Mengembalikan jumlah maksimal dari formulir berderet tambahan untuk digunakan. Secara awalan, mengembalikan atribut `InlineModelAdmin.max_num`.

  Timpa metode ini untuk secara program menentukan jumlah maksimal dari formulir berderet tambahan. Sebagai contoh, ini mungkin berdasarkan pada instance model (dilewatkan sebagai argumen kata kunci `obj`):

      class BinaryTreeAdmin(admin.TabularInline):
          model = BinaryTree

          def get_max_num(self, request, obj=None, **kwargs):
              max_num = 10
              if obj and obj.parent:
                  return max_num - 5
              return max_num

InlineModelAdmin.get_min_num(request, obj=None, **kwargs)

  Mengembalikan jumlah minimal dari formulir berderet untuk digunakan. Secara awalan, mengembalikan atribut `InlineModelAdmin.min_num`.

  Timpa metode ini untuk secara program menentukan jumlah minimal dari formulir berderet tambahan. Sebagai contoh, ini mungkin berdasarkan pada instance model (dilewatkan sebagai argumen kata kunci `obj`):

InlineModelAdmin.has_add_permission(request, obj)

  Harus mengembalikan `True` jika menambahkan obyek dalam barisan diizinkan, `False` sebaliknya. `obj` adalah obyek induk sedang disunting atau `None` ketika menambahkan induk baru.

InlineModelAdmin.has_change_permission(request, obj=None)

  Harus mengembalikan `True` jika menyunting obyek dalam barisan diizinkan, `False` sebaliknya. `obj` adalah obyek induk sedang disunting.

InlineModelAdmin.has_delete_permission(request, obj=None)

  Harus mengembalikan `True` jika menghapus obyek dalam barisan diizinkan, `False` sebaliknya. `obj` adalah obyek induk sedang disunting.

Catatan

The `obj` argument passed to `InlineModelAdmin` methods is the parent object being edited or `None` when adding a new parent.

### Bekerja dengan sebuah model dengan dua atau lebih foreign key pada model induk yang sama.

Itu terkadang memungkinkan memiliki lebih dari satu foreign key pada model yang sama. Ambil model ini sebagai contoh:

    from django.db import models

    class Person(models.Model):
        name = models.CharField(max_length=128)

    class Friendship(models.Model):
        to_person = models.ForeignKey(
            Person, on_delete=models.CASCADE, related_name="friends"
        )
        from_person = models.ForeignKey(
            Person, on_delete=models.CASCADE, related_name="from_friends"
        )

Jika anda ingin memperlihatkan sebuah berderet pada halaman tambah/rubah admin `Person` anda butuh secara jelas menentukan foreign key sejak itu tidak dapat melakukannya otomatis:

    from django.contrib import admin
    from myapp.models import Friendship, Person

    class FriendshipInline(admin.TabularInline):
        model = Friendship
        fk_name = "to_person"

    class PersonAdmin(admin.ModelAdmin):
        inlines = [
            FriendshipInline,
        ]

    admin.site.register(Person, PersonAdmin)

### Bekerja dengan model banyak-ke-banyak

By default, admin widgets for many-to-many relations will be displayed on whichever model contains the actual reference to the `ManyToManyField`. Depending on your `ModelAdmin` definition, each many-to-many field in your model will be represented by a standard HTML `<select multiple>`, a horizontal or vertical filter, or a `raw_id_fields` widget. However, it is also possible to replace these widgets with inlines.

Misalkan kita memiliki model berikut:

    from django.db import models

    class Person(models.Model):
        name = models.CharField(max_length=128)

    class Group(models.Model):
        name = models.CharField(max_length=128)
        members = models.ManyToManyField(Person, related_name="groups")

Jika anda ingin memperlihatkan hubungan many-yo-many menggunakan sebuah berderet, anda dapat melakukan juga dengan menentukan sebuah obyek `InlineModelAdmin` untuk hubungan:

    from django.contrib import admin
    from myapp.models import Group

    class MembershipInline(admin.TabularInline):
        model = Group.members.through

    class GroupAdmin(admin.ModelAdmin):
        inlines = [
            MembershipInline,
        ]
        exclude = ["members"]

    admin.site.register(Group, GroupAdmin)

Ada dua fitur perlu dicatat di contoh ini.

Pertama-tama - kelas `MembershipInline` mengacu `Group.members.through`. Atribut `through` adalah sebuah acuan pada model yang mengelola hubungan many-to-many. Model ini secara otomatis dibuat oleh Django ketika anda menentukan bidang many-to-many.

Kedua, `GroupAdmin` harus secara manual mengeluarkan bidang `members`. Django menampilkan sebuah widget admin untuk bidang many-to-many pada model yang menentukan hubungan (di kasus ini, `Group`). Jika anda ingin menggunakan sebuah model berderet untuk mewakili hubungan many-to-many, anda harus memberitahu admin Django tidak memperlihatkan widget ini - sebaliknya anda akan berakhir dengan dua widget pada halaman admin anda untuk mengelola hubungan.

Catat bahwa ketika menggunakan teknik ini sinyal `m2m_changed` tidak dipicu. Ini adalah karena sejauh admin yang bersangkutan, `through` hanya sebuah model dengan dua bidang foreign key daripada hubungan many-to-many.

Dalam semua hal lainnya, `InlineModelAdmin` persisnya sama seperti lainnya. Anda dapat menyesuaikan penampilan menggunakan apapun dari sifat-sifat `ModelAdmin` biasa.

### Bekerja dengan model perantara many-to-many

Ketika anda menentukan sebuah model perantara menggunakan argumen `through` pada sebuah `ManyToManyField`, admin tidak akan menampilkan sebuah widget secara awalan. Ini karena setiap instance dari model perantara membutuhkan lebih informasi dari dapat diperlihatkan dalam sebuah widget tunggal, dan tata letak dibutuhkan untuk widget banyak akan beragam bergantung pada model perantara.

However, we still want to be able to edit that information inline. Fortunately, we can do this with inline admin models. Suppose we have the following models:

    from django.db import models

    class Person(models.Model):
        name = models.CharField(max_length=128)

    class Group(models.Model):
        name = models.CharField(max_length=128)
        members = models.ManyToManyField(Person, through="Membership")

    class Membership(models.Model):
        person = models.ForeignKey(Person, on_delete=models.CASCADE)
        group = models.ForeignKey(Group, on_delete=models.CASCADE)
        date_joined = models.DateField()
        invite_reason = models.CharField(max_length=64)

        class Meta:
            constraints = [
                models.UniqueConstraint(
                    fields=["person", "group"], name="unique_person_group"
                )
            ]

Langkah pertama dalam memperlihatkan model perantara ini di admin adalah menentukan sebuah kelas berderet untuk model `Membership`:

    class MembershipInline(admin.TabularInline):
        model = Membership
        extra = 1

This example uses the default `InlineModelAdmin` values for the `Membership` model, and limits the extra add forms to one. This could be customized using any of the options available to `InlineModelAdmin` classes.

Sekarang membuat tampilan admin untuk model `Person` dan `Group`:

    class PersonAdmin(admin.ModelAdmin):
        inlines = [MembershipInline]

    class GroupAdmin(admin.ModelAdmin):
        inlines = [MembershipInline]

Akhirnya, daftar model `Person` dan `Group` dengan situs admin:

    admin.site.register(Person, PersonAdmin)
    admin.site.register(Group, GroupAdmin)

Sekarang situs admin anda dipersiapkan untuk menyunting obyek-obyek `Membership` berderet dari antara `Person` atau `Group` di halaman rincian.

### Menggunakan hubungan umum sebagai sebuah berderet

Itu memungkinkan menggunakan sebuah berderet dengan umum obyek terkait. Mari kita katakan anda memiliki model-model berikut:

    from django.contrib.contenttypes.fields import GenericForeignKey
    from django.contrib.contenttypes.models import ContentType
    from django.db import models

    class Image(models.Model):
        image = models.ImageField(upload_to="images")
        content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
        object_id = models.PositiveIntegerField()
        content_object = GenericForeignKey("content_type", "object_id")

    class Product(models.Model):
        name = models.CharField(max_length=100)

Jika anda ingin menyunting dan membuat sebuah instance `Image` pada `Product`, tampilan tambah/rubah anda dapat menggunakan `GenericTabularInline` atau `GenericStackedInline` (kedua subkelas-subkelas dari `GenericInlineModelAdmin`) disediakan oleh `admin`. Mereka menerapkan tata letak penampakan datar dan bertumpuk untuk formulir mewakili obyek berderet, masing-masing, seperti pasangan bukan-umum mereka. Mereka berperilaku seperti berderet lainnya. Di `admin.py` anda untuk contoh aplikasi ini:

    from django.contrib import admin
    from django.contrib.contenttypes.admin import GenericTabularInline

    from myapp.models import Image, Product

    class ImageInline(GenericTabularInline):
        model = Image

    class ProductAdmin(admin.ModelAdmin):
        inlines = [
            ImageInline,
        ]

    admin.site.register(Product, ProductAdmin)

Lihat contenttypes documentation untuk informasi lebih spesifik.

## Menimpa cetakan admin

You can override many of the templates which the admin module uses to generate the various pages of an admin site. You can even override a few of these templates for a specific app, or a specific model.

### Setel direktori cetakan admin proyek

The admin template files are located in the django/contrib/admin/templates/admin directory.

Untuk menimpa satu atau lebih mereka, pertama buat sebuah direktori `admin` dalam direktori `templates` proyek anda. Ini dapat berupa apapun dari direktori anda tentukan dalam pilihan `DIRS` dari backend `DjangoTemplates` dalam pengaturan `TEMPLATES`. Jika anda telah menyesuaikan pilihan `'loaders'`, pastikan `'django.template.loaders.filesystem.Loader'` muncul sebelum `'django.template.loaders.app_directories.Loader'` sehingga cetakan penyesuaian anda akan ditemukan oleh sistem pemuat cetakan sebelum mereka yang disertakan dengan `django.contrib.admin`.

Dalam direktori `admin` ini, buat sub-direktori diberi nama setelah aplikasi anda. Dalam subdirektori aplikasi ini buat sub-direktori dinamai setelah model anda. Catat, bahwa aplikasi admin akan menghuruf kecilkan nama model ketika mencari direktori, jadi pastikan anda memberi nama direktori dalam semua huruf kecil jika anda akan menjalankan aplikasi anda pada sistem berkas kasus-sensitif.

To override an admin template for a specific app, copy and edit the template from the django/contrib/admin/templates/admin directory, and save it to one of the directories you just created.

Sebagai contoh, jika kami ingin menambah sebuah alat pada tampilan daftar rubah untuk semua model-model dalam sebuah aplikasi bernama `my_app`, kami akan menyalin `contrib/admin/templates/admin/change_list.html` ke direktori `templates/admin/my_app/` dari proyek kami, dan membuat apapun perubahan dibutuhkan.

Jika kami ingin menambah sebuah alat pada tampilan daftar rubah untuk hanya model tertentu bernama 'Page', kami akan menyalin berkas sama itu ke direktori `templates/admin/my_app/page` dari proyek kami.

### Menimpa lawan mengganti cetakan admin

Karena rancangan modular dari cetakan-cetakan admin, itu biasanya tidak perlu dan tidak dianjurkan untuk mengganti keseluruhan cetakan. Itu adalah hampir selalu lebih baik menimpa hanya bagian dari cetakan yang anda butuh dirubah.

Untuk melanjutkan contoh diatas, kami ingin menambah sebuah tautan baru dekat pada alat `History` untuk model `Page`. Setelah mencari di `change_form.html` kami menentukan bahwa kami hanya butuh menimpa blok `object-tools-items`, Oleh karena itu disini adalah `change_form.html` baru kami :

    {% extends "admin/change_form.html" %}
    {% load i18n admin_urls %}
    {% block object-tools-items %}
        <li>
            <a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% translate "History" %}</a>
        </li>
        <li>
            <a href="mylink/" class="historylink">My Link</a>
        </li>
        {% if has_absolute_url %}
            <li>
                <a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% translate "View on site" %}</a>
            </li>
        {% endif %}
    {% endblock %}

Dan itu dia! Jika kami menempatkan berkas ini di direktori `templates/admin/my_app`, tautan kami akan muncul pada formulir rubah untuk semua model dalam my_app.

### Cetakan-cetakan yang mungkin menimpa per aplikasi atau model

Tidak setiap cetakan di `contrib/admin/templates/admin` mungkin ditimpa per aplikasi atau per model. Berikut dapat:

- `actions.html`

- `app_index.html`

- `change_form.html`

- `change_form_object_tools.html`

- `change_list.html`

- `change_list_object_tools.html`

- `change_list_results.html`

- `date_hierarchy.html`

- `delete_confirmation.html`

- `object_history.html`

- `pagination.html`

- `popup_response.html`

- `prepopulated_fields_js.html`

- `search_form.html`

- `submit_line.html`

For those templates that cannot be overridden in this way, you may still override them for your entire project by placing the new version in your `templates/admin` directory. This is particularly useful to create custom 404 and 500 pages.

Catatan

Beberapa dari cetakan-cetakan admin, seperti `change_list_results.html` digunakan untuk membangun etiket penyertaaan penyesuaian. Ini mungkin ditimpa, tetapi dalam kasus-kasus seprti itu anda mungkin lebih baik membuat versi anda sendiri dari etiket dalam pertanyaan dan memberikan itu sebuah nama berbeda. Cara itu anda dapat menggunakannya selektif.

### Cetakan akar dan masuk

Jika anda berharap merubah cetakan indeks, masuk atau keluar, anda lebih baik membuat instance `AdminSite` anda sendiri (lihat dibawah), dan merubah sifat-sifat `AdminSite.index_template` , `AdminSite.login_template` atau `AdminSite.logout_template`.

## Theming support

The admin uses CSS variables to define colors and fonts. This allows changing themes without having to override many individual CSS rules. For example, if you preferred purple instead of blue you could add a `admin/base.html` template override to your project:

    {% extends 'admin/base.html' %}

    {% block extrastyle %}{{ block.super }}
    <style>
    html[data-theme="light"], :root {
      --primary: #9774d5;
      --secondary: #785cab;
      --link-fg: #7c449b;
      --link-selected-fg: #8f5bb2;
    }
    </style>
    {% endblock %}

The list of CSS variables are defined at django/contrib/admin/static/admin/css/base.css.

Dark mode variables, respecting the prefers-color-scheme media query, are defined at django/contrib/admin/static/admin/css/dark_mode.css. This is linked to the document in `{% block dark-mode-vars %}`.

## `extrabody` block

New in Django 5.2.

You can add custom HTML, JavaScript, or other content to appear just before the closing `</body>` tag of templates that extend `admin/base.html` by extending the `extrabody` block. For example, if you want an alert to appear on page load you could add a `admin/base.html` template override to your project:

    {% extends 'admin/base.html' %}

    {% block extrabody %}
        {{ block.super }}
        <script>
            document.addEventListener('DOMContentLoaded', function() {
                window.alert('Welcome!');
            });
        </script>
    {% endblock extrabody %}

## Obyek `AdminSite`

class AdminSite(name='admin')

  Sebuah situs administratif Django diwakili oleh sebuah instance dari `django.contrib.admin.sites.AdminSite`; secara awalan, sebuah instance dari kelas ini dibuat sebagai `django.contrib.admin.site` dan anda dapat mendaftar model-model anda dan instance-instance `ModelAdmin` dengan itu.

  Jika anda ingin menyesuaikan situs admin awalan, anda dapat :ref:`override it `.

  Ketika mendirikan sebuah instance dari sebuah `AdminSite`, anda dapat menyediakan sebuah nama instance unik menggunakan argumen `name` pada pembangun. Nama instance ini digunakan untuk mencirikan instance, khususnya ketika reversing admin URLs. Jika tidak ada nama instance disediakan, sebuah nama instace awalan dari `admin` akan digunakan. Lihat Menyesuaikan kelas AdminSite. untuk sebuah contoh dari menyesuaikan kelas `AdminSite`.

django.contrib.admin.sites.all_sites

  A `WeakSet` contains all admin site instances.

### Atribut `AdminSite`

Cetakan dapat dikesampingkan atau diperpanjang berdasarkan cetakan admin seperti digambarkan di Menimpa cetakan admin.

AdminSite.site_header

  The text to put at the top of each admin page, as a `<div>` (a string). By default, this is "Django administration".

AdminSite.site_title

  Teks untuk ditaruh pada akhir dari setiap `<title>` halaman admin (sebuah string). Secara awalan, ini adalah "Situs admin Django".

AdminSite.site_url

  URL untuk tautan "View site" pada atas dari setiap halaman admin. Secara awalan, `site_url` adalah `/`. Setel itu menjadi `None` untuk memindahkan tautan

  Untuk situs-situs berjalan pada subjalur, metode `each_context()` memeriksa jika permintaan saat ini mempunyai kumpulan `request.META['SCRIPT_NAME']` dan menggunakan nilai itu jika `site_url``tidak menyetel ke sesuatu selain dari ``/`.

AdminSite.index_title

  Teks untuk ditaruh di atas dari halaman index admin (deretan karakter). Secara awalan, ini adalah "Administrasi Situs".

AdminSite.index_template

  Jalur pada cetakan penyesuaian yang akan digunakan oleh tampilan indeks utama situs admin.

AdminSite.app_index_template

  Jalur pada cetakan penyesuaian yang akan digunakan oleh tampilan indeks aplikasi situs admin.

AdminSite.empty_value_display

  Deretan karakter yang digunakan untuk menampilkan nilai kosong di daftar perubahan situs admin. Awalan pada sebuah garis. Nilai dapat juga ditimpa pada dasar per `ModelAdmin` dan pada bidang penyesuaian dalam `ModelAdmin` dengan mengatur sebuah atribut `empty_value_display` pada bidang. Lihat `ModelAdmin.empty_value_display` sebagai contoh.

AdminSite.enable_nav_sidebar

  A boolean value that determines whether to show the navigation sidebar on larger screens. By default, it is set to `True`.

AdminSite.final_catch_all_view

  A boolean value that determines whether to add a final catch-all view to the admin that redirects unauthenticated users to the login page. By default, it is set to `True`.

  Peringatan

  Setting this to `False` is not recommended as the view protects against a potential model enumeration privacy issue.

AdminSite.login_template

  Jalur pada cetakan penyesuaian yang akan digunakan oleh tampilan masuk situs admin.

AdminSite.login_form

  Subkelas dari `AuthenticationForm` yang akan digunakan oleh tampilan masuk situs admin.

AdminSite.logout_template

  Jalur pada cetakan penyesuaian yang akan digunakan oleh tampilan keluar situs admin.

AdminSite.password_change_form
  New in Django 6.0.

  Subclass of `PasswordChangeForm` that will be used by the admin site password change view.

AdminSite.password_change_template

  Jalur pada cetakan penyesuaian yang akan digunakan oleh tampilan merubah sandi situs admin.

AdminSite.password_change_done_template

  Jalur pada cetakan penyesuaian yang akan digunakan oleh tampilan selesai merubah sandi situs admin.

### Cara `AdminSite`

AdminSite.each_context(request)

  Dikembalikan sebuah kamus dari variabel-variabel untuk menaruh di konteks cetakan untuk setiap halaman di situs admin.

  Menyertakan variabel-variabel berikut dan nilai-nilai secara awalan:

  - `site_header`: `AdminSite.site_header`

  - `site_title`: `AdminSite.site_title`

  - `site_url`: `AdminSite.site_url`

  - `has_permission`: `AdminSite.has_permission()`

  - `available_apps`: sebuah daftar aplikasi dari application registry tersedia untuk pengguna saat ini. Setiap masukan dalam daftar adalah sebuah kamus mewakili sebuah aplikasi dengan kunci berikut:

    - `app_label`: label aplikasi

    - `app_url`: URL dari indeks aplikasi di admin

    - `has_module_perms`: sebuah boolean mengindikasikan jika menampilkan dan mengakses dari halaman indeks modul diizinkan untuk pengguna saat ini

    - `models`: sebuah daftar dari model tersedia di aplikasi

    Setiap model adalah kamus dengan kunci-kunci berikut:

    - `model`: the model class

    - `object_name`: nama kelas dari model

    - `name`: nama jamak dari model

    - `perms`: `dict` melacak perizinan `add`, `change`, `delete`, dan `view`

    - `admin_url`: URL daftar rubah admin untuk model

    - `add_url`: URL admin untuk menambah instance model baru

  - `is_popup`: whether the current page is displayed in a popup window

  - `is_nav_sidebar_enabled`: `AdminSite.enable_nav_sidebar`

  - `log_entries`: `AdminSite.get_log_entries()`

AdminSite.get_app_list(request, app_label=None)

  Returns a list of applications from the application registry available for the current user. You can optionally pass an `app_label` argument to get details for a single app. Each entry in the list is a dictionary representing an application with the following keys:

  - `app_label`: label aplikasi

  - `app_url`: URL dari indeks aplikasi di admin

  - `has_module_perms`: sebuah boolean mengindikasikan jika menampilkan dan mengakses dari halaman indeks modul diizinkan untuk pengguna saat ini

  - `models`: sebuah daftar dari model tersedia di aplikasi

  - `name`: name of the application

  Each model is a dictionary with the following keys:

  - `model`: the model class

  - `object_name`: nama kelas dari model

  - `name`: nama jamak dari model

  - `perms`: `dict` melacak perizinan `add`, `change`, `delete`, dan `view`

  - `admin_url`: URL daftar rubah admin untuk model

  - `add_url`: URL admin untuk menambah instance model baru

  Lists of applications and models are sorted alphabetically by their names. You can override this method to change the default order on the admin index page.

AdminSite.has_permission(request)

  Mengembalikan `True` jika pengguna untuk `HttpRequest` yang diberikan mempunyai perizinan untuk melihat setidaknya satu halaman dalam situs admin. Awalan mewajibkan kedua `User.is_active` dan `User.is_staff` menjadi `True`.

AdminSite.register(model_or_iterable, admin_class=None, **options)

  Mendaftarkan kelas model yang diberikan (atau kelas-kelas berulang) dengan `admin_class` yang diberikan. Awalan `admin_class` pada `ModelAdmin` (pilihan admin awalan). Jika argumen kata kunci diberikan -- misalnya `list_display` -- mereka akan diberlakukan sebagai pilihan pada kelas admin.

  Raises `ImproperlyConfigured` if a model is abstract. and `django.contrib.admin.exceptions.AlreadyRegistered` if a model is already registered.

AdminSite.unregister(model_or_iterable)

  Unregisters the given model class (or iterable of classes).

  Raises `django.contrib.admin.exceptions.NotRegistered` if a model isn't already registered.

AdminSite.get_model_admin(model)

  Returns an admin class for the given model class. Raises `django.contrib.admin.exceptions.NotRegistered` if a model isn't registered.

AdminSite.get_log_entries(request)

  Returns a queryset for the related `LogEntry` instances, shown on the site index page. This method can be overridden to filter the log entries by other criteria.

### Mengkaitkan instance `AdminSite` kedalam URLconf anda

The last step in setting up the Django admin is to hook your `AdminSite` instance into your URLconf. Do this by pointing a given URL at the `AdminSite.urls` method. It is not necessary to use `include()`.

Di contoh ini, kami mendaftarkan instance `AdminSite` awalan `django.contrib.admin.site` pada URL `/admin/`

    # urls.py
    from django.contrib import admin
    from django.urls import path

    urlpatterns = [
        path("admin/", admin.site.urls),
    ]

### Menyesuaikan kelas `AdminSite`.

If you'd like to set up your own admin site with custom behavior, you're free to subclass `AdminSite` and override or add anything you like. Then, create an instance of your `AdminSite` subclass (the same way you'd instantiate any other Python class) and register your models and `ModelAdmin` subclasses with it instead of with the default site. Finally, update `myproject/urls.py` to reference your `AdminSite` subclass.

`myapp/admin.py`

    from django.contrib import admin

    from .models import MyModel

    class MyAdminSite(admin.AdminSite):
        site_header = "Monty Python administration"

    admin_site = MyAdminSite(name="myadmin")
    admin_site.register(MyModel)

`myproject/urls.py`

    from django.urls import path

    from myapp.admin import admin_site

    urlpatterns = [
        path("myadmin/", admin_site.urls),
    ]

Catat bahwa anda tidak mungkin ingin penemuan otomatis dari modul-modul `admin` ketika menggunakan instance `AdminSite` anda sendiri sejak anda akan mengimpor semua per-aplikasi modul-modul `admin` dalam modul `myproject.admin` anda. Ini berarti anda butuh menaruh `'django.contrib.admin.apps.SimpleAdminConfig'` daripada `'django.contrib.admin'` dalam pengaturan `INSTALLED_APPS` anda.

### Menimpa situs admin awalan

Anda dapat menimpa `django.contrib.admin.site` awalan dengan mengatur atribut `default_site` `AppConfig` penyesuaian pada jalur impor bertitik dari salah satu subkelas `AdminSite` atau callable yang mengembalikan sebuah instance situs.

`myproject/admin.py`

    from django.contrib import admin

    class MyAdminSite(admin.AdminSite): ...

`myproject/apps.py`

    from django.contrib.admin.apps import AdminConfig

    class MyAdminConfig(AdminConfig):
        default_site = "myproject.admin.MyAdminSite"

`myproject/settings.py`

    INSTALLED_APPS = [
        # ...
        "myproject.apps.MyAdminConfig",  # replaces 'django.contrib.admin'
        # ...
    ]

### Banyak situs admin di URLconf yang sama

You can create multiple instances of the admin site on the same Django-powered website. Create multiple instances of `AdminSite` and place each one at a different URL.

Dalam contoh ini, URL fitur `/basic-admin/` and `/advanced-admin/` versi terpisah dari situs admin -- menggunakan instance-instance `AdminSite` `myproject.admin.basic_site` dan `myproject.admin.advanced_site`, masing-masing:

    # urls.py
    from django.urls import path
    from myproject.admin import advanced_site, basic_site

    urlpatterns = [
        path("basic-admin/", basic_site.urls),
        path("advanced-admin/", advanced_site.urls),
    ]

Instance `AdminSite` mengambil argumen tunggal pada pembangun mereka, nama mereka, yang dapat apapun anda suka. Argumen ini menjadi awalan pada nama-nama URL untuk tujuan dari reversing them. Ini hanya dibutuhkan jika anda sedang menggunakan lebih dari satu `AdminSite`.

### Menambahkan tampilan ke situs admin

Just like `ModelAdmin`, `AdminSite` provides a `get_urls()` method that can be overridden to define additional views for the site. To add a new view to your admin site, extend the base `get_urls()` method to include a pattern for your new view.

Catatan

Tampian apapun anda bangun yang menggunakan cetakan admin, atau perpankang cetakan admin dasar, harus menyetel `request.current_app` sebelum membangun cetakan. Itu harus disetel antara `self.name` jika tampilan anda pada sebuah `AdminSite` atau `self.admin_site.name` jika tampilan anda pada sebuah `ModelAdmin`.

### Menambahkan fitur penyetelan kembali sandi

Anda dapat menambah sebuah fitur penyetelan kembali sandi pada situs admin dengan menambahkan beberapa baris pada URLconf anda. Khususnya, tambah tambahkan empat pola ini:

    from django.contrib import admin
    from django.contrib.auth import views as auth_views

    path(
        "admin/password_reset/",
        auth_views.PasswordResetView.as_view(
            extra_context={"site_header": admin.site.site_header}
        ),
        name="admin_password_reset",
    ),
    path(
        "admin/password_reset/done/",
        auth_views.PasswordResetDoneView.as_view(
            extra_context={"site_header": admin.site.site_header}
        ),
        name="password_reset_done",
    ),
    path(
        "reset/<uidb64>/<token>/",
        auth_views.PasswordResetConfirmView.as_view(
            extra_context={"site_header": admin.site.site_header}
        ),
        name="password_reset_confirm",
    ),
    path(
        "reset/done/",
        auth_views.PasswordResetCompleteView.as_view(
            extra_context={"site_header": admin.site.site_header}
        ),
        name="password_reset_complete",
    ),

(Ini menganggap anda telah menambahkan admin pada `admin/` dan diwajibkan bahwa anda menaruh URL dimulai dengan `^admin/` sebelum baris yang menyertakan aplikasi admin itu sendiri).

Kehadiran dari URL bernama `admin_password_reset` akan menyebabkan sebuah tautan "forgotten your password?" muncul pada halaman masuk admin awalan dibawah kotak sandi.

## Obyek `LogEntry`

class models.LogEntry

  Kelas `LogEntry` melacak penambahan, perubahan, penghapusan dari obyek melalui antarmuka admin.

### Atribut `LogEntry`

LogEntry.action_time

  Tanggal dan waktu dari tindakan.

LogEntry.user

  Pengguna (sebuah instance `AUTH_USER_MODEL`) yang melakukan tindakan.

LogEntry.content_type

  `ContentType` dari obyek dirubah.

LogEntry.object_id

  Perwakilan tekstual dari primary key obyek yang telah dirubah.

LogEntry.object_repr

  `repr()` obyek setelah perubahan.

LogEntry.action_flag

  Jenis dari tindakan dicatat: `ADDITION`, `CHANGE`, `DELETION`.

  Sebagai contoh, untuk mendapatkan daftar dari semua tambahan selesai melalui admin:

      from django.contrib.admin.models import ADDITION, LogEntry

      LogEntry.objects.filter(action_flag=ADDITION)

LogEntry.change_message

  Gambaran rincian dari perubahan. Dalam kasus sebuah penyuntingan, sebagai contoh, pesan mengandung daftar dari bidang-bidang terseunting. Situs admin Django membentuk isi ini sebagai struktur JSON, sehingga `get_change_message()` mengubah komposisi sebuah pesan diterjemahkan dalam bahasa pengguna saat ini. Penyesuaian kode mungkin menyetel ini sebagai string polos. Anda disarankan menggunakan metode `get_change_message()` untuk mengambil nilai ini daripada mengakses itu langsung.

### Cara `LogEntry`

LogEntry.get_edited_object()

  Sebuah jalan pintas yang mengembalikan obyek diacukan.

LogEntry.get_change_message()

  Bentuk dan terjemahkan `change_message` kedalam bahasa pengguna saat ini. Pesan-pesan dibuat sebelum Django 1.10 akan selalu diperlihatkan dalam bahasa yang mereka telah masuk.

## Membalikkan URL admin

Ketika `AdminSite` disebarkan, tampilan disediakan oleh situs itu dapat diakses menggunakan URL reversing system Django.

`AdminSite` menyediakan corak URL bernama berikut:

Halaman | Nama URL | Parameter
--- | --- | ---
Indeks | `indeks` |
Masuk | `login` |
Keluar | `keluar` |
Ubah sandi | `password_change` |
Merubah sandi selesai | `password_change_done` |
i18n JavaScript | `jsi18n` |
Halaman indeks aplikasi | `app_list` | `app_label`
Pengalihan ke halaman obyek | `view_on_site` | `content_type_id`, `object_id`

Setiap instance `ModelAdmin` menyediakan sebuah tambahan sekumpulan dari URL bernama:

Halaman | Nama URL | Parameter
--- | --- | ---
Daftar rubah | `{{ app_label }}_{{ model_name }}_changelist` |
Tambah | `{{ app_label }}_{{ model_name }}_add` |
Riwayat | `{{ app_label }}_{{ model_name }}_history` | `object_id`
Hapus | `{{ app_label }}_{{ model_name }}_delete` | `object_id`
Ubah | `{{ app_label }}_{{ model_name }}_change` | `object_id`

`UserAdmin` menyediakan sebuah URL bernama:

Halaman | Nama URL | Parameter
--- | --- | ---
Ubah sandi | `auth_user_password_change` | `user_id`

URL bernama ini didaftarkan dengan namespace aplikasi `admin`, dan dengan sebuah namespace instance berhubungan pada nama dari instance Site.

So - if you wanted to get a reference to the Change view for a particular `Choice` object (from the polls application) in the default admin, you would call:

    >>> from django.urls import reverse
    >>> c = Choice.objects.get(...)
    >>> change_url = reverse("admin:polls_choice_change", args=(c.id,))

Ini akan menemukan instance terdaftar pertama dari aplikasi admin (apapun nama instance), dan memutuskan untuk tampilan untuk merubah instance `poll.Choice` dalam instance itu.

If you want to find a URL in a specific admin instance, provide the name of that instance as a `current_app` hint to the reverse call. For example, if you specifically wanted the admin view from the admin instance named `custom`, you would need to call:

    >>> change_url = reverse("admin:polls_choice_change", args=(c.id,), current_app="custom")

Untuk rincian lebih, lihat dokumentasi pada reversing namespaced URLs.

Untuk mengizinkan membalikan paling mudah dari url-url admin dalam cetakan, Django menyediakan penyaring `admin_urlname` yang mengambil sebuah tindakan sebagai argumen:

    {% load admin_urls %}
    <a href="{% url opts|admin_urlname:'add' %}">Add user</a>
    <a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>

Tindakan dalam contoh-contoh diatas mencocokan bagian terakhir dari nama-nama URL untuk instance-instance `ModelAdmin` digambarkan diatas. Variabel 11opts`` dapat berupa obyek-obyek apapun yang mempunyai sebuah atribut `app_label` dan `model_name` dan biasanya dipasok oleh tampilan-tampilan admin untuk model saat ini.

## The `display` decorator

display(*, boolean=None, ordering=None, description=None, empty_value=None)

  This decorator can be used for setting specific attributes on custom display functions that can be used with `list_display` or `readonly_fields`:

      @admin.display(
          boolean=True,
          ordering="-publish_date",
          description="Is Published?",
      )
      def is_published(self, obj):
          return obj.publish_date is not None

  This is equivalent to setting some attributes (with the original, longer names) on the function directly:

      def is_published(self, obj):
          return obj.publish_date is not None

      is_published.boolean = True
      is_published.admin_order_field = "-publish_date"
      is_published.short_description = "Is Published?"

  Also note that the `empty_value` decorator parameter maps to the `empty_value_display` attribute assigned directly to the function. It cannot be used in conjunction with `boolean` -- they are mutually exclusive.

  Use of this decorator is not compulsory to make a display function, but it can be useful to use it without arguments as a marker in your source to identify the purpose of the function:

      @admin.display
      def published_year(self, obj):
          return obj.publish_date.year

  In this case it will add no attributes to the function.

## Penghias `staff_member_required`

staff_member_required(redirect_field_name='next', login_url='admin:login')

  This decorator is used on the admin views that require authorization. A view decorated with this function will have the following behavior:

  - Jika pengguna masuk, adalah anggota staf (`User.is_staff=True`), dan aktif (`User.is_active=True`), kerjakan tampilan secara biasa.

  - Sebaliknya, permintaan akan dialihkan ke URL ditentukan oleh parameter `login_url`, dengan jalur aslinya diminta dalam sebuah variabel string permintaan ditentukan oleh `redirect_field_name`. Sebagai contoh: `/admin/login/?next=/admin/polls/question/3/`.

  Contoh penggunaan:

      from django.contrib.admin.views.decorators import staff_member_required

      @staff_member_required
      def my_view(request): ...