# dokumentasi Django 2.2.9.dev20191202104323

# Tindakan admin

Alir kerja dasar dari admin Django adalah, dalam kulit kacang, "pilih sebuah obyek, kemudian rubah itu." Ini bekerja baik untuk kebanyakan penggunaan kasus. Bagaimanapun, jika anda butuh perubahan sama ke banyak obyek sekali waktu, alir kerja ini bisa sangat membosankan.

Di kasus-kasus ini, admin Django membiarkan anda menulis dan mendaftar "actions" -- fungsi sederhana yang dipanggil dengan daftar dari obyek-obyek terpilih pada halaman daftar rubah.

Jika anda mencari daftar perubahan apapun di admin, anda akan melihat fitur ini di tindakan; Django dikirim dengan tindakan "menghapus obyek terpilih" tersedia untuk semua model. Sebagai contoh, ini adalah modul pengguna dari aplikasi `django.contrib.auth` pasang-tetap Django :

Peringatan

Tindakan "hapus obyek-obyek terpilih" menggunakan `QuerySet.delete()` untuk alasan efesiensi, yang mempunyai surat keberatan yang penting: metode `delete()` model anda tidak akan dipanggil.

Jika anda berharap menimpa perilaku ini, anda dapat menimpa `ModelAdmin.delete_queryset()` atau menulis penyesuaian tindakan yang melakukan penghapusan dalam perilaku anda pilih -- sebagai contoh, dengan memanggil `Model.delete()` untuk setiap dari barang terpilih.

Untuk latar belakang lebih pada penghapusan jumlah besar, lihat dokumentasi pada object deletion.

Baca untuk menemukan bagaimana menambah tindakan anda sendiri ke daftar ini.

## Menulis tindakan

Cara mudah untukmenjelaskan tindakan adalah dengan contoh, jadi mari kita selami.

Penggunaan kasus umum untuk tindakan admin adalah memperbaharui dalam jumlah besar dari sebuah model. Bayangkan aplikasi berita sederhana dengan model `Article`:

    from django.db import models

    STATUS_CHOICES = [
        ('d', 'Draft'),
        ('p', 'Published'),
        ('w', 'Withdrawn'),
    ]

    class Article(models.Model):
        title = models.CharField(max_length=100)
        body = models.TextField()
        status = models.CharField(max_length=1, choices=STATUS_CHOICES)

        def __str__(self):
            return self.title

Tugas utama kami mungkin lakukan dengan sebuah model seperti ini adalah memperbaharui sebuah keadaan article dari "draft" menjadi "published". Kami dapat dengan mudah melakukan ini di admin satu artikel pada sekali waktu, tetapi jika kami ingin menerbitkan-jumlah besar kelompok dari artikel, itu akan membosankan. Jadi, mari kita menulis sebuah tindakan yang membuat kita merubah sebuah keadaan artikel menjadi "published."

### Menulis fungsi tindakan

Pertama, kami akan butuh menulis sebuah fungsi yang dipanggil ketika tindakan dipicu dari admin. Tindakan berbagi fungsi hanya fungsi biasa yang mengambil tiga argumen:

- `ModelAdmin` saat ini
- Sebuah `HttpRequest` mewakili permintaan saat ini,
- Sebuah `QuerySet` mengandung sekumpulan dari obyek-obyek terpilih oleh pengguna.

Fungsi terbitan-artikel-ini kami tidak butuh `ModelAdmin` atau obyek permintaan, tetapi kami akan menggunakan queryset:

    def make_published(modeladmin, request, queryset):
        queryset.update(status='p')

Catatan

Untuk penampilan terbaik, kami sedang menggunakan update method queryset. Jenis-jenis lain dari tindakan mungkin butuh berurusan dengan setiap obyek pribadi; di kasus-kasus ini kami hanya cukup berulang terhadap queryset:

    for obj in queryset:
        do_something_with(obj)

Itu benar-benar semuanya ada adalah menulis sebuah tindakan! Bagaimanapun, kami akan mengambil satu atau lebih langkah pilihan-tetapi-berguna dan memberikan tindakan sebuah judul "nice" dalam admin. Secara awalan, tindakan ini akan muncul dalam daftar tindakan sebagai "Make published" -- nama fungsi, dengan garis bawah diganti oleh ruang. Tidak apa-apa, tetai kami dapat menyediakan lebih baik, nama lebih ramah-manusia dengan memberikan fungsi make_published` sebuah atribut `short_description`:

    def make_published(modeladmin, request, queryset):
        queryset.update(status='p')
    make_published.short_description = "Mark selected stories as published"

Catatan

Ini mungkin terlihat akrab; pilihan `list_display` admin menggunakan teknik sama untuk menyediakan gambaran dapat dibaca-manusia untuk fungsi callback terdaftar disana, juga.

### Menambahkan tindakan pada `ModelAdmin`

Selanjutnya, kami akan butuh menginformasikan `ModelAdmin` kami dari tindakan. Ini bekerja seperti piliha konfigurasi lain apapun. Jadi, `admin.py` lengkap dengan tindakan dan pendaftarannya akan terlihat seperti:

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

    def make_published(modeladmin, request, queryset):
        queryset.update(status='p')
    make_published.short_description = "Mark selected stories as published"

    class ArticleAdmin(admin.ModelAdmin):
        list_display = ['title', 'status']
        ordering = ['title']
        actions = [make_published]

    admin.site.register(Article, ArticleAdmin)

Kode akan memberikan kami sebuah daftar rubah admin yang terlihat sesuatu seperti ini:

Itu benar-benar semua yang ada untuk itu! Jika anda sedang gatal menulis tindakan anda sendiri, anda sekarang cukup mengetahui untuk memulai. Sisanya dari dokumen ini hanya mencangkup teknik-teknik lebih lanjut.

### Penanganan kesalahan di tindakan

Jika ada kondisi kesalahan mendatang yang mungkin muncul selagi menjalankan tindakan anda, anda harus anggun menginformasikan pengguna dari masalah. Ini berarti menangani pengecualian dan menggunakan `django.contrib.admin.ModelAdmin.message_user()` untuk memperlihatkan gambaran yang ramah pengguna dari masalah di tanggapan.

## Teknik-teknik tindakan lanjutan

Ada sepasang pilihan tambahan dan kemungkinan anda dapat menggunakan lebih pilihan lanjutan

### Tindakan sebagai metode `ModelAdmin`

Contoh diatas menunjukkan tindakan `make_published` ditentukan sebagai sebuah fungsi sederhana. Itu sangat baik, tetapi itu tidak sempurna dari titik rancangan kode dari tampilan: sejak tindakan erat digabungkan ke obyek `Article`, itu masuk akal mengkaitkan tindakan ke obyek `ArticleAdmin` itu sendiri.

Itu cukup mudah melakukan:

    class ArticleAdmin(admin.ModelAdmin):
        ...

        actions = ['make_published']

        def make_published(self, request, queryset):
            queryset.update(status='p')
        make_published.short_description = "Mark selected stories as published"

Perhatikan pertama yang kami telah pindahkan `make_published` kedalam metode dan dinamai kembali parameter `modeladmin` pada `self`, dan kedua kami telah sekarang menaruh string `'make_published'` dalam `actions` daripada acuan fungsi langsung. Ini mengatakan `ModelAdmin` untuk mencari tindakan sebagai sebuah metode.

Menentukan tindakan sebagai metode memberikan tindakan lebih mudah, akses idiomatis ke `ModelAdmin` itu sendiri, mengizinkan tindakan memanggil metode apapun disediakan oleh admin.

Sebagai contoh, kami dapat menggunakan `self` pada sebuah pesan sekejab ke pengguna menginformasikan dia bahwa tindakan telah berhasil:

    class ArticleAdmin(admin.ModelAdmin):
        ...

        def make_published(self, request, queryset):
            rows_updated = queryset.update(status='p')
            if rows_updated == 1:
                message_bit = "1 story was"
            else:
                message_bit = "%s stories were" % rows_updated
            self.message_user(request, "%s successfully marked as published." % message_bit)

Ini membuat tindakan cocok apa yang admin itu sendiri lakukan setelah berhasil melakukan sebuah tindakan:

### Tindakan yang menyediakan halaman menengah

Secara awalan, setelah sebuah tindakan dilakukan pengguna cukup mengalihkan kembali kehalaman daftar rubah asli. Bagaimanapun, beberapa tindakan, khususnya satu lebih rumit, akan butuh mengembalikan halaman menengah. Sebagai contoh, tindakan hapus siap-pakai meminta untuk penegasan sebelum menghapus obyek-obyek terpilih

Untuk menyediakan sebuah halaman menengah, cukup kembalikan sebuah `HttpResponse` (atau subkelas) dari tindakan anda. Sebagai contoh, anda mungkin menulis sebuah fungsi ekspor sederhana yang menggunakan serialization functions Django unutk membuang beberapa obyek-obyek terpilih sebagai JSON:

    from django.core import serializers
    from django.http import HttpResponse

    def export_as_json(modeladmin, request, queryset):
        response = HttpResponse(content_type="application/json")
        serializers.serialize("json", queryset, stream=response)
        return response

Umumnya, sesuatu seperti diatas tidak dianggap ide yang hebat. Kebanyakan dari waktu, praktik terbaik akan mengembalikan sebuah `HttpResponseRedirect` dan pengalihan pengguna ke sebuah tamilan anda telah tulis, melewatkan daftar dari obyek-obyek terpilih di string permintaan GET. Ini mengizinkan anda menyediakan logika interaksi rumit pada halaman penengah. Sebagai contoh, jika anda ingin menyediakan fungsi ekspor lebih rumit, anda ingin membiarkan penggua memilih bentuk, dan kemungkinan daftar dari bidang-bidang untuk disertakan di export. Hal terbaik untuk melakukan adalah menulis tindakan kecil yang cukup mengalihkan tampilan ekspor penyesuaian anda:

    from django.contrib.contenttypes.models import ContentType
    from django.http import HttpResponseRedirect

    def export_selected_objects(modeladmin, request, queryset):
        selected = queryset.values_list('pk', flat=True)
        ct = ContentType.objects.get_for_model(queryset.model)
        return HttpResponseRedirect('/export/?ct=%s&ids=%s' % (
            ct.pk,
            ','.join(str(pk) for pk in selected),
        ))

Seperti anda dapat lihat, tindakan adalah bagian sederhana; semua logika rumit akan milik di tampilan ekspor anda. Ini akan butuh berurusan dengan obyek-obyek dari jenis apapun, dengan demikian bisnis dengan `ContentType`.

Meunlis tampilan ini adalah sisa dari sebuah latihan ke pembaca.

### Membuat tindakan tersedia lebar-situs

`AdminSite.``add_action`(action, name=None)

  Beberapa tindakan adalah terbaik jika mereka membuat tersedia pada setiap obyek di situs admin -- tindakan ekspor ditentukan diatas akan menjadi calon bagus. Anda dapat membuat sebuah tindakan secara global tersedia menggunakan `AdminSite.add_action()`. Sebagai contoh:

      from django.contrib import admin

      admin.site.add_action(export_selected_objects)

  Ini membuat tindakan `export_selected_objects` secara global tersedia sebagai sebuah tindakan bernama "export_selected_objects". Anda dapat dengan jelas memberikan tindakan sebuah nama -- bagus jika anda kemudian ingin secara program remove the action -- dengan melewatkan argumen kedua ke `AdminSite.add_action()`:

      admin.site.add_action(export_selected_objects, 'export_selected')

### Meniadakan tindakan

Terkadang anda butuh meniadakan beberapa tindakan -- khususnya itu registered site-wide -- untuk obyek-obyek tertentu. Ada sedikit cara anda dapat meniadakan tindakan:

#### Meniadakan tindakan lebar-situs

`AdminSite.``disable_action`(name)

  Jika anda butuh meniadakan sebuah site-wide action anda dapat memanggil `AdminSite.disable_action()`.

  Sebagai contoh, anda dapat menggunakan metode ini memindahkan tindakan "delete selected objects" siap-pakai:

      admin.site.disable_action('delete_selected')

  Sekali anda telah melakukan diatas, tindakan itu akan tidak lagi tersedia lebar-situs.

  Jika, bagaimanapun, anda butuh mengadakan kembali tindakan ditiadakan-global untuk satu model tertentu, cukup daftar itu dengan jelas di daftar `ModelAdmin.actions` anda:

      # Globally disable delete selected
      admin.site.disable_action('delete_selected')

      # This ModelAdmin will not have delete_selected available
      class SomeModelAdmin(admin.ModelAdmin):
          actions = ['some_other_action']
          ...

      # This one will
      class AnotherModelAdmin(admin.ModelAdmin):
          actions = ['delete_selected', 'a_third_action']
          ...

#### Meniadakan semua tindakan untuk `ModelAdmin` tertentu

Jika anda ingin tidak tindakan dalam jumlah besar tersedia untuk `ModelAdmin` yang diberikan, cukup setel `ModelAdmin.actions` menjadi `None`:

    class MyModelAdmin(admin.ModelAdmin):
        actions = None

Ini memberitahu `ModelAdmin` untuk tidak memperlihatkan atau mengizinkan tindakan apapun, termasuk site-wide actions apapun.

#### Tindakan mengadakan dan meniadakan bersyarat

`ModelAdmin.``get_actions`(request)

  Akhirnya, anda dapat secara kondisional mengadakan atau meniadakan tindakan-tindakan pada sebuah per-permintaan (dan karenanya berdasarkan per-pengguna) dengan mengutamakan `ModelAdmin.get_actions()`.

  Ini mengembalikan sebuah kamus dari tindakan diizinkan. Kunci-kunci adalah nama-nama tindkan, dan nilai-nilai adalah tuple `(function, name, short_description)`.

  Sebagai contoh, jika anda hanya ingin pengguna yang namanya dimulai dengan 'J' untuk dapat menghapus obyek-pbyek dalam jumlah besar:

      class MyModelAdmin(admin.ModelAdmin):
          ...

          def get_actions(self, request):
              actions = super().get_actions(request)
              if request.user.username[0].upper() != 'J':
                  if 'delete_selected' in actions:
                      del actions['delete_selected']
              return actions

### Pengaturan perizinan untuk tindakan

New in Django 2.1.

Tindakan-tindakan mungkin membatasi ketersediaan pada pengguna dengan perizinan khusus dengan mengatur sebuah atribut `allowed_permissions` pada fungsi tindakan:

    def make_published(modeladmin, request, queryset):
        queryset.update(status='p')
    make_published.allowed_permissions = ('change',)

Tindakan `make_published()` hanya akan tersedia pada pengguna yang melewatkan pemeriksaan `ModelAdmin.has_change_permission()`.

Jika `allowed_permissions` mempunyai lebih dari satu perizinan, tindakan akan tersedia selama pengguna melewatkan setidaknya satu pemeriksaan.

Nilai-nilai tersedia untuk `allowed_permissions` dan metode pemeriksaan terkait adalah:

- `'add'`: `ModelAdmin.has_add_permission()`
- `'change'`: `ModelAdmin.has_change_permission()`
- `'delete'`: `ModelAdmin.has_delete_permission()`
- `'view'`: `ModelAdmin.has_view_permission()`

Anda dapat menentukan nilai lain apapun selama anda menerapkan metode `has__permission(self, request)` sesuai pada `ModelAdmin`.

Sebagai contoh:

    from django.contrib import admin
    from django.contrib.auth import get_permission_codename

    class ArticleAdmin(admin.ModelAdmin):
        actions = ['make_published']

        def make_published(self, request, queryset):
            queryset.update(status='p')
        make_published.allowed_permissions = ('publish',)

        def has_publish_permission(self, request):
            """Does the user have the publish permission?"""
            opts = self.opts
            codename = get_permission_codename('publish', opts)
            return request.user.has_perm('%s.%s' % (opts.app_label, codename))