【初心者】【Python/Django】駆け出しWebエンジニアがDjangoチュートリアルをやってみた～その7～

今回はadminフォームをカスタマイズしていきます。

## admin フォームのカスタマイズ

現在のadminフォームを確認していきます。

```python:polls/admin.py
from django.contrib import admin

# Register your models here.
from .models import Question

admin.site.register(Question)

```
「http://127.0.0.1:8000/admin/polls/question/5/change/」にアクセスすると以下の表示がされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/abfc8eb4-bd88-9f47-95bf-941dcedf29f0.png)

### admin.pyを修正する①

adminフォームをカスタマイズするためにはadmin.pyを修正します。
QuestionAdminクラスを作成し、question_text、pub_dateの表示順序を変更します。
もともとはquestion_textの下にpub_dateでしたが、以下のコードではpub_dateの下にquestion_textとします。

```python:polls/admin.py
from django.contrib import admin

# Register your models here.
from .models import Question


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


admin.site.register(Question, QuestionAdmin)

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/ed135b67-75ae-1818-3674-8ed0f0c334d6.png)

### admin.pyを修正する②

```python:polls/admin.py

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date']}),
    ]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/74248b70-4653-f34f-9a51-c53889f00bd3.png)

## リレーションを張ったオブジェクトの追加

Questionが表示されることは確認できましたが、Questionに紐づくChoiceも同時に表示できないものでしょうか？
チュートリアルを進めていきます。

```python:polls/admin.py
from django.contrib import admin
from .models import Question, Choice

admin.site.register(Choice)
```
Choiceが追加されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/b6eb1132-4090-eb50-0269-bc53670751b3.png)
選択肢「The sky」に紐づく質問は選択肢を開かないと確認できません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/0dfc390e-ed61-5757-b982-00aaf1be2154.png)
選択肢「The sky」は質問「What's this?」に紐づいていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/5b56d3c7-0bdf-c045-01e1-a4156ae2f29b.png)

質問と選択肢を同時に表示します。
ChoiceInlineでは3つの空白のChoiceフィールドを表示すると指定しています。

```python:polls/admin.py
from django.contrib import admin

# Register your models here.
from .models import Question, Choice


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)
```
質問「What's this?」には選択肢「Not much」「The sky」があり、3つの空白選択肢欄が表示されています。
。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/ab192481-f76a-b2ce-e4d6-c90d3fdd6838.png)

Choiceの表示が縦長になっているので、テーブル形式で表示するように修正しましょう。

```python:polls/admin.py
class ChoiceInline(admin.TabularInline):
```

テーブル形式で表示され、すっきりしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/b78249a5-1bdb-c94b-fd90-b83c5ea60504.png)

## 管理サイトのチェンジリストページをカスタマイズする

チェンジリストは「http://127.0.0.1:8000/admin/<アプリ名>/<クラス名>/」で表示される内容です。

```python:polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]
    list_display = ('question_text', 'pub_date', 'was_published_recently')
```
「http://127.0.0.1:8000/admin/polls/question/」を開きます。
今までは「QUESTION TEXT」カラムのみでしたが、新たに「DATA PUBLISHED」「PUBLISHED RECENTLY?」カラムが追加されました。

「QUESTION TEXT」「DATA PUBLISHED」カラムは並び替えに対応しています。
一方で「PUBLISHED RECENTLY?」カラムは並び替えに対応していないのですが、理由はメソッドの戻り値を表示しているからです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/d3371fad-cd93-95c5-dd51-870eeb980c48.png)

「PUBLISHED RECENTLY?」で絞り込みをするためにfilterを使いましょう。

```python:polls/models.py
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('data published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return timezone.now() - datetime.timedelta(days=1) <= self.pub_date <= timezone.now()
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'
```
list_filterを追加します。

```python
class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]
    list_display = ('question_text', 'pub_date', 'was_published_recently')
    list_filter = ['pub_date']
```
サイドバーにfilterが表示されました。
「すべての期間 ("Any date")」「今日 ("Today")」「今週 ("Past 7 days")」「今月 ("This month")」「今年 ("This year")」で絞り込みできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/bedeb47e-8325-f227-ccd5-667b9898a33e.png)

続いて検索窓を作成します。

```python:polls/admin.py
search_fields = ['question_text']
```

画面上部に検索窓が表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763383/0185d19e-76cb-5898-0720-4e107c24c504.png)

以上で終了となります。ありがとうございました。