はじめに
「[Django]管理画面の一覧表示部分に、(表示対象のテーブルで外部キーなどでの関連もさせていない)別テーブルのフィールドを表示する」
最終的に結構単純でしたが、同じようなことをしている人が少なくて割と悩んだのでメモ。
多分ドキュメントに丁寧に目を通した人にとっては当たり前のことかも。
やりたいこと
上の画面を下のような表示にしたかったのですが、この時、DBの構成は下記のER図のようになっており、日時系の値とそれ以外の値は別DBのフィールドのため、単純にlist_display
で追加することができなかった。
[ER図]
(記事用に適当に書き換えたので、ER図と下の方のコードの整合性保ってない部分もあるかも)
要点
特に重要なのは下記の部分ですが、一応全貌を載せておきます。
重要部分1
def plan_start_datetime(self, obj):
list_got_objects = list(Datetime.objects.all().values_list('plan_start_datetime', flat=True))
return list_got_objects
※1:取得したい情報の条件(例:「id=1」など)
重要部分2
list_display = (
'plan_start_datetime',
)
要点1.
<テーブル名>.objects.all()
の戻り値はQuerySetなので、values_list()
で値を取得する必要がある。
要点2.
values_list()
で取得した値をスライスして取得した「文字列」をlist_display
に渡す。
以下、全貌
models.py
# coding: utf-8
from django.db import models
from django.utils import timezone
from django.core.validators import MaxValueValidator
# コードがforeign keyとして使用されるため、このクラスを先に定義している
class M_branch(models.Model):
def __str__(self):
return self.name
code = models.CharField(max_length=4, primary_key=True)
name = models.CharField(max_length=128)
# コードがforeign keyとして使用されるため、このクラスを先に定義している
class M_workplace(models.Model):
def __str__(self):
return self.name
branch_code = models.ForeignKey(M_branch, on_delete=models.CASCADE)
code = models.CharField(max_length=4)
name = models.CharField(max_length=128)
class Report(models.Model):
def __str__(self):
return self.application_id
application_id = models.CharField(max_length=32, primary_key=True)
branch_code = models.ForeignKey(M_branch, on_delete=models.DO_NOTHING)
workplace_code = models.ForeignKey(M_workplace, on_delete=models.DO_NOTHING)
class Datetime(models.Model):
def __str__(self):
return self.plan_start_datetime
application_id = models.OneToOneField(Report, on_delete=models.CASCADE)
plan_start_datetime = models.DateTimeField()
plan_end_datetime = models.DateTimeField()
actual_start_datetime = models.DateTimeField()
actual_end_datetime = models.DateTimeField()
admin.py
from django.contrib import admin
from .models import Report, Datetime, Participant, M_branch, M_workplace
# TODO DatetimeやParticipantテーブルから必要な情報を取得して同じ表に表示する
class ReportAdmin(admin.ModelAdmin):
fieldsets = [
('申請ID', {'fields': ['application_id']}),
('支部コード', {'fields': ['branch_code']}),
('職場コード', {'fields': ['workplace_code']}),
]
list_display = ('application_id',
'branch_code',
'workplace_code',
'plan_start_datetime',
'plan_end_datetime',
'actual_start_datetime',
'actual_end_datetime',
)
def plan_start_datetime(self, obj):
list_got_objects = list(Datetime.objects.all().values_list('plan_start_datetime', flat=True))
return plan_start_datetime
plan_start_datetime.short_description = 'plan_start_datetime'
def plan_end_datetime(self, obj):
list_got_objects = list(Datetime.objects.all().values_list('plan_end_datetime', flat=True))
return plan_end_datetime
plan_end_datetime.short_description = 'plan_end_datetime'
def actual_start_datetime(self, obj):
list_got_objects = list(Datetime.objects.all().values_list('actual_start_datetime', flat=True))
return actual_start_datetime
actual_start_datetime.short_description = 'actual_start_datetime'
def actual_end_datetime(self, obj):
list_got_objects = list(Datetime.objects.all().values_list('actual_end_datetime', flat=True))
return actual_end_datetime
actual_end_datetime.short_description = 'actual_end_datetime'
class M_branchAdmin(admin.ModelAdmin):
fieldsets = [
('支部コード', {'fields': ['code']}),
('支部名', {'fields': ['name']}),
]
list_display = ('name', 'code')
class M_workplaceAdmin(admin.ModelAdmin):
fieldsets = [
('支部コード', {'fields': ['branch_code']}),
('職場コード', {'fields': ['code']}),
('職場名', {'fields': ['name']}),
]
list_display = ('name', 'code', 'branch_code')
admin.site.register(Report, ReportAdmin)
admin.site.register(M_branch, M_branchAdmin)
admin.site.register(M_workplace, M_workplaceAdmin)
以上。