# Dokumentasi Django 5.2.8

# Menulis aplikasi Django kedua anda, bagian 7

Tutorial ini memulai dimana Tutorial 6 ditinggalkan. Kami sedang melanjutkan aplikasi poling-jaringan dan akan fokus pada menyesuaikan pembangkitan otomatis situs admin Django yang pertama kami jelajahi dalam in Tutorial 2.

Dimana mendapatkan bantuan:

Jika anda memiliki masalah melalui tutorial ini, harap geser ke Getting Help bagian dari FAQ.

## Sesuaikan bentuk admin

Dengan mendaftarkan model `Question` dengan `admin.site.register(Question)`, Django dapat membangun bentuk perwakilan awal. Sering, anda akan menginginkan menyesuaikan bagaimana bentuk admin kelihatan dan bekerja. Anda akan melakukan ini dengan memberitahu Django pilihan anda ingin ketika anda mendaftar obyek.

Mari kita lihat bagaimana ini bekerja dengan mengurutkan kembali bidang di formulir sunting. Ganti baris `admin.site.register(Question)` dengan:

`polls/admin.py`

    from django.contrib import admin

    from .models import Question

    class QuestionAdmin(admin.ModelAdmin):
        fields = ["pub_date", "question_text"]

    admin.site.register(Question, QuestionAdmin)

Anda akan mengikuti corak ini -- buat sebuah kelas admin model, kemudian lewati dia sebagai argumen kedua ke `admin.site.register()` -- setiap saat anda butuh merubah pilihan admin untuk sebuah model.

Perubahan khusus ini diatas membuat "Tanggal penerbitan" datang sebelum bidang "Pertanyaan" :

Ini tidak hebat dengan hanya dua bidang, tetapi untuk bentuk admin dengan lusinan bidang, memilih urutan intuitif adalah rincian kegunaan penting.

Dan berbicara formulir dengan lusinan bidang, anda mungkin ingin memisahkan formulir menjadi kumpulan bidang:

`polls/admin.py`

    from django.contrib import admin

    from .models import Question

    class QuestionAdmin(admin.ModelAdmin):
        fieldsets = [
            (None, {"fields": ["question_text"]}),
            ("Date information", {"fields": ["pub_date"]}),
        ]

    admin.site.register(Question, QuestionAdmin)

Unsur pertama dari setiap tuple di `fieldsets` adalah judul dari fieldset. Ini adalah apa formulir kami kelihatan seperti sekarang:

## Menambahkan obyek terhubung

OKE, kami mempunyai halaman admin Pertanyaan, tetapi `Question` mempunyai banyak `Choice`, dan halaman admin tidak menampilkan pilihan.

Masih.

Ada dua cara menyelesaikan masalah ini. pertama adalah mendaftarkan `Choice` dengan admin seperti yang kami lakukan dengan `Question`:

`polls/admin.py`

    from django.contrib import admin

    from .models import Choice, Question

    # ...
    admin.site.register(Choice)

Sekarang "Pilihan" adalah pilihan tersedia di admin Django. Bentuk "Tambah pilihan" kelihatan seperti ini:

Di bentuk itu, bidang "Pertanyaan" adalah kotak pilih mengandung setiap pertanyaan di basisdata. Django mengetahui bahwa `ForeignKey` harus diwakilkan di admin sebagai kotal `<select>`. Di kasus kami, hanya satu pertanyaan ada di titik ini.

Juga catat bahwa tautan "Tambah pertanyaan lain" dengan dengan "Pertanyaan." Setiap objek dengan hubungan `ForeignKey` ke yang lainnya mendapatkan ini secara gratis. Ketika anda mengklik "Tambah pertanyaan lain", anda akan mendapatkan jendela sembulan dengan formulir "Tambah pertanyaan". Jika anda memmpunyai sebuah pertanyaan di jendela tersebutdan klik "Simpan", Django akan menyimpan pertanyaan ke basisdata dan secara dinamis menambahkannya sebagai pilihan terpilih pada formulir "Tambah pilihan" yang anda lihat.

Tetapi, sungguh, ini bukan cara efisien dari menambahkan obyek `Choice` ke sistem. Akan lebih baik jika anda dapat menambahkan sekumpulan Pilihan langsung ketika anda membuat obyek `Question`. Mari kita membuatnya terjadi.

Pindahkan pemanggilan `register()` untuk model `Choice`. Lalu, sunting kode pendaftaran `Question` untuk dibaca:

`polls/admin.py`

    from django.contrib import admin

    from .models import Choice, Question

    class ChoiceInline(admin.StackedInline):
        model = Choice
        extra = 3

    class QuestionAdmin(admin.ModelAdmin):
        fieldsets = [
            (None, {"fields": ["question_text"]}),
            ("Date information", {"fields": ["pub_date"], "classes": ["collapse"]}),
        ]
        inlines = [ChoiceInline]

    admin.site.register(Question, QuestionAdmin)

Ini memberitahu Django: "obyek `Choice` sedang disunting pada halaman admin `Question`. Secara awal, cukup menyediakan bidang untuk 3 pilihan."

Muat halaman "Tambahan pertanyaan" untuk melihat bagaimana kelihatannya:

Dia bekerja seperti ini: Terdapat tiga bagian untuk Pilihan terhubung -- sesuai ditentukan oleh `extra` -- dan setiap waktu anda kembali ke halaman "Rubah" untuk obyek sudah-sibuat, anda mendapatkan tiga ekstra bagian lain.

At the end of the three current slots you will find an "Add another Choice" link. If you click on it, a new slot will be added. If you want to remove the added slot, you can click on the X to the top right of the added slot. This image shows an added slot:

Satu masalah kecil, meskipun. Itu mengambil banyak lahan layar untuk menampilkan semua bidang untuk memasukkan objek `Choice` terkait. Untuk alasan itu, Django menawarkan cara datar dari menampilkan objek terkait di barisan. Untuk menggunakan itu, rubah pernyataan `ChoiceInline` untuk membaca:

`polls/admin.py`

    class ChoiceInline(admin.TabularInline): ...

Dengan `TabularInline` (daripada `StackedInline`), obyek terhubung ditampilkan lebih rapat, bentuk berbasiskan-tabel:

Catat bahwa ada tambahan "Hapus?" kolom yang mengizinkan memindahkan baris ditambahkan menggunakan tombol "Tambah Pilihan lain" dan baris yang sudah disimpan.

## Sesuaiakan daftar perubahan admin

Sekarang bahwa halaman admin Question kelihatan bagus, mari kita membuat beberapa perubahan untuk "daftar rubah" halaman -- satu yang menampilkan semua pertanyaan di sistem.

Inilah yang terlihat seperti pada saat ini:

By default, Django displays the `str()` of each object. But sometimes it'd be more helpful if we could display individual fields. To do that, use the `list_display` admin option, which is a list of field names to display, as columns, on the change list page for the object:

`polls/admin.py`

    class QuestionAdmin(admin.ModelAdmin):
        # ...
        list_display = ["question_text", "pub_date"]

Untuk ukuran terbaik, mari juta juga sertakan metode `was_published_recently()` dari Tutorial 2:

`polls/admin.py`

    class QuestionAdmin(admin.ModelAdmin):
        # ...
        list_display = ["question_text", "pub_date", "was_published_recently"]

Sekarang pertanyaan halaman daftar perubahan kelihatan seperti ini:

Anda dapat meng klik di kepala kolom untuk mengurutkan nilai tersebut -- kecuali di kasus kepala `was_published_recently`, karena mengurutkan berdasarkan keluaran dari cara sewenang-wenang tidak didukung. Juga catat bahwa kepala kolom untuk `was_published_recently` adalah, secara awal, nama dari cara (dengan garis bawah ditandai dengan spasi), dan setiap baris mengandung string mewakili dari keluaran.

You can improve that by using the `display()` decorator on that method (extending the `polls/models.py` file that was created in Tutorial 2), as follows:

`polls/models.py`

    from django.contrib import admin

    class Question(models.Model):
        # ...
        @admin.display(
            boolean=True,
            ordering="pub_date",
            description="Published recently?",
        )
        def was_published_recently(self):
            now = timezone.now()
            return now - datetime.timedelta(days=1) <= self.pub_date <= now

Untuk informasi lebih pada properti yang dapat dikonfigurasikan melalui penghias lihat `list_display`.

Sunting berkas `polls/admin.py` anda kembali dan tambah perbaikan ke halaman daftar perubahan `Question` : saringan menggunakan `list_filter`. Tambah baris berikut ke `QuestionAdmin`:

    list_filter = ["pub_date"]

Itu menambahkan batang sisi "Saringan" yang membiarkan orang menyaring daftar perubahan dengan bidang `pub_date`:

Jenis dari saringan ditampilkan tergantung pada jenis dari bidang anda saringkan. karena `pub_date` adalah sebuah `DateTimeField`, Django mengetahui untuk memberikan pilihan saringan sesuai: "Tanggal kapanpun", "7 hari terakhir"," Bulan ini", "Tahun ini".

Ini adalah pembentukan baik. Mari kita menambahkan beberapa kemampuan pencarian

    search_fields = ["question_text"]

Itu menambah kotak pencarian di bagian atas dari daftar rubah. Ketika seseorang memasukkan istilah pencarian, Django akan mencari bidang `question_text`. Anda dapat menggunakan sebanyak bidang anda suka -- meskipun karena itu menggunakan query `LIKE` dibelakang layar, membatasi angka bidan gpencarian untuk angka yang beralasan akan membuatnya mudah bagi basisdata anda melakukan pencarian.

Sekarang juga waktu bagus untuk mencatat bahwa daftar perubahan diberikan ke anda bebas halaman Awalnya adalah menampilkan 100 barang per halaman. `Change list pagination`, `search boxes`, `filters`, `date-hierarchies`, dan `column-header-ordering` semua kerja bersama seperti anda berpikir mereka seharusnya.

## Sesuaikan admin lihat dan rasakan

Jelas, mempunyai "Administrasi Django" pada atas dari setiap halaman admin adalah menggelikan. Itu adalah hanya teks placeholder.

Anda dapat merubahnya, meskipun, menggunakan sistem cetakan Django. Admin Django ditenagai oleh Django itu sendiri, dan antarmukanya menggunakan sistem cetakan Django sendiri.

### Menyesuaikan cetakan proyek anda

Create a `templates` directory in your `djangotutorial` directory. Templates can live anywhere on your filesystem that Django can access. (Django runs as whatever user your server runs.) However, keeping your templates within the project is a good convention to follow.

Buka berkas pengaturan anda (`mysite/settings.py`, ingat) dan tambah pilihan `DIRS` di pengaturan `TEMPLATES` :

`mysite/settings.py`

    TEMPLATES = [
        {
            "BACKEND": "django.template.backends.django.DjangoTemplates",
            "DIRS": [BASE_DIR / "templates"],
            "APP_DIRS": True,
            "OPTIONS": {
                "context_processors": [
                    "django.template.context_processors.request",
                    "django.contrib.auth.context_processors.auth",
                    "django.contrib.messages.context_processors.messages",
                ],
            },
        },
    ]

`DIRS` adalah daftar dari direktori sistem berkas untuk memeriksa ketika memuat cetakan Django; dia adalah jalur pencarian.

Mengatur cetakan

Sama seperti berkas-berkas tetap, kami dapat mempunyai semua cetakan bersama-sama, dalam satu direktori cetakan besar, dan itu akan bekerja sempurna. Bagaimanapun, cetakan-cetakan yang milik aplikasi tertentu harus ditempatkan dalam direktori cetakan aplikasi (contoh `polls/templates`) daripada (`templates`) proyek. Kami akan mengobrolkan lebih rinci dalam :doc:`reusable apps tutorial ` mengapa kami melakukan ini.

Now create a directory called `admin` inside `templates`, and copy the template `admin/base_site.html` from within the default Django admin template directory in the source code of Django itself (django/contrib/admin/templates) into that directory.

Dimana berkas sumber Django?

Jika anda mempunyai kesulitan dimana berkas sumber Django ditempatkan di sistem anda, jalankan perintah berikut:

/ 

    $ python -c "import django; print(django.__path__)"

    ...\> py -c "import django; print(django.__path__)"

Kemudian, sunting berkas dan ganti `{{ site_header|default:_('Django administration') }}` (termasuk tanda buka kurung bergelombang) dengan nama situs anda sendiri untuk melihatnya cocok. Anda akan berakhir dengan bagian seperti kode:

    {% block branding %}
    <div id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></div>
    {% if user.is_anonymous %}
      {% include "admin/color_theme_toggle.html" %}
    {% endif %}
    {% endblock %}

Kami menggunakan pendekatan ini untuk mengajarkan anda bagaimana menimpa cetakan. Di proyek sesungguhnya, anda mungkin menggunakan atribut `django.contrib.admin.AdminSite.site_header` untuk lebih mudah membuat penyesuaian tertentu.

Berkas cetakan ini mengandung banyak teks seperti `{% block branding %}` dan `{{ title }}`. Etiket `{%` dan `{{` adalah bagian dari bahasa cetakan Django. Ketika Django membangun `admin/base_site.html`, bahasa cetakan akan menilai untuk menghasilkan halaman HTML akhir, sama seeprti kami lihat di Tutorial 3.

Catat bahwa cetakan admin awalan Django dapat ditimpa. Untuk menimpa cetakan, lakukan hal sama anda lakukan dengan `base_site.html` -- salin itu dari direktori awalan kedalam direktori penyesuaian anda, dan buat perubahan.

### Menyesuaikan cetakan aplikasi anda

Pembaca cerdik akan bertanya: Tetapi jika `DIRS` kosong secara awal, bagaimana Django menemukan cetakan admin awal? Jawabannya adalah, sejak `APP_DIRS` disetel ke `True`, Django otomatis mencari subdirektori `templates/` dalam setiap paket aplikasi, untuk digunakan sebagai kembali (jangan lupa bahwa `django.contrib.admin` adalah sebuah aplikasi).

Aplikasi jejak pendapat kami tidak sangat rumit dan tidak butuh penyesuaian cetakan admin. Tetapi jika itu tumbuh lebih mutkahir dan membutuhkan perubahan dari cetakan admin standar Django untuk beberapa fungsinya, itu akan lebih bijaksana untuk merubah cetakan aplikasi, daripada itu di proyek. Lewat situ, anda dapat menyertakan aplikasi jejak pendapat di proyek baru apapun dan terjamin bahwa dia akan menemukan cetakan penyesuaian dia butuhkan.

Lihat dokumentasi memuat cetakan untuk informasi lebih tentang bagaimana Django menemukan cetakannya.

## Sesuaikan halaman index admin

Pada catatan sama, anda mungkin ingin menyesuaikan penampilan dan rasa dari halaman index admin Django.

Secara awal, dia menampilkan semua aplikasi di `INSTALLED_APPS` yang telah didaftarkan dengan aplikasi admin, dalam urutan alfabet. Anda mungkin ingin membuat perubahan signifikan pada tata letak. Lagi pula, index mungkin halaman paling penting dari admin, dan dia harus mudah digunakan.

The template to customize is `admin/index.html`. (Do the same as with `admin/base_site.html` in the previous section -- copy it from the default directory to your custom template directory). Edit the file, and you'll see it uses a template variable called `app_list`. That variable contains every installed Django app. Instead of using that, you can hardcode links to object-specific admin pages in whatever way you think is best.

When you're comfortable with the admin, read part 8 of this tutorial to learn how to use third-party packages.