外部キー関係が存在しない場合に、インラインで表示する関連オブジェクトのセットを手動で指定することは可能ですか?
# Parent
class Diary(models.Model):
day = models.DateField()
activities = models.TextField()
# Child
class Sleep(models.Model):
start_time = models.DateTimeField()
end_time = models.DateTimeField()
class SleepInline(admin.TabularInline):
model=Sleep
def get_queryset(self, request):
# Return all Sleep objects where start_time and end_time are within Diary.day
return Sleep.objects.filter(XXX)
class DiaryAdmin(admin.ModelAdmin):
inlines = (SleepInline, )
Diary
モデル管理者にstart_time
がDiary.day
と同じ日に等しいSleep
モデルのインラインを表示させたい。問題は、Sleep
モデルにForeignKey
からDiary
がないことです(代わりに、日付の使用によって関係が暗黙的に示されます)。
上記を使用すると、Djangoはすぐに次のように文句を言います
<class 'records.admin.SleepInline'>: (admin.E202) 'records.Sleep' has no ForeignKey to 'records.Diary'.
関連するSleep
インスタンスをDiary
管理ページにインラインで表示するにはどうすればよいですか?
まず、ロジックの欠点を説明します。
お気づきのように、追加の欠点は、リレーショナル機能を使用できないことです。 InlineAdminはリレーショナル機能であるため、「管理者を機能させる」と言うのと同じように、ボルトを緩めるためにハンマーを要求する必要があります。
しかし...管理者はModelFormを利用します。したがって、 formset (同じ理由でインラインフォームセットにすることはできません)を使用してフォームを作成し、そのフォームセットを自分で保存する場合は、可能であるはずです。 InlineFormsetとInlineAdminの要点は、関連するモデルからのフォームセットの生成を容易にすることであり、そのためには関係を知る必要があります。
そして最後に、 rlsを追加 してカスタムページを作成できます。admin/ base.htmlテンプレートを拡張すると、レイアウトとjavascriptコンポーネントにアクセスできるようになります。
Django adminインラインがForeignKey
フィールド(またはManyToManyField
、OneToOneField
)を中心に構築されているという事実を回避することはできません。私はあなたの目標を理解しています。_Diary.day
_フィールドと_Sleep.start_time
_フィールドの間の「日付の整合性」を管理する必要がないようにすることです。つまり、外部キー関係が実際にDiary.day == Sleep.start_time.date()
Django ForiegnKey
フィールドには to_fieldプロパティ があり、FKはid
以外の列にインデックスを付けることができます。ただし、 DateTimeField
のSleep
とDateField
のDiary
の場合、そのDateTimeField
を分割する必要があります。また、ForeignKey
は、関係の「1」側で一意の何かに関連している必要があります。_Diary.day
_は_unique=True
_に設定する必要があります。
このアプローチでは、モデルは次のようになります。
_from Django.db import models
# Parent
class Diary(models.Model):
day = models.DateField(unique=True)
activities = models.TextField()
# Child
class Sleep(models.Model):
diary = models.ForeignKey(Diary, to_field='day', on_delete=models.CASCADE)
start_time = models.TimeField()
end_time = models.DateTimeField()
_
そしてあなたの_admin.py
_はただ
_from Django.contrib import admin
from .models import Sleep, Diary
class SleepInline(admin.TabularInline):
model=Sleep
@admin.register(Diary)
class DiaryAdmin(admin.ModelAdmin):
inlines = (SleepInline, )
_
_Sleep.start_time
_に日付がなくなったとしても、Django Adminはあなたが期待するものであり、「日付の冗長性」を回避します。
より現実的な(そして問題のある)ユースケースを前もって考えて、すべてのユーザーが1日に1つの日記を持つことができると言います。
_class Diary(models.Model):
user = models.ForeignKey(User)
day = models.DateField()
activities = models.TextField()
class Meta:
unique_together = ('user', 'day')
_
次のようなものを書きたい
_class Sleep(models.Model):
diary = models.ForeignKey(Diary, to_fields=['user', 'day'], on_delete=models.CASCADE)
_
ただし、Django 1.11にはそのような機能はなく、それを追加することについての真剣な議論も見つかりません。確かに、Postgresやその他のSQLDBMSでは複合外部キーが許可されています。=から印象を受けます。 Djangoソースはオプションを開いたままにしています: https://github.com/Django/django/blob/stable/1.11.x/Django/db/models/fields/ related.py#L621 将来の実装を示唆しています。
最後に、 https://pypi.python.org/pypi/Django-composite-foreignkey 最初は面白そうに見えますが、「実際の」複合外部キーを作成せず、Djangoの管理者とも連携しません。 。
これは、Nested_adminライブラリを使用して実現できます。だからmyapp/admin.py
from nested_admin.nested import NestedStackedInline, NestedModelAdmin
class SleepInline(NestedStackedInline):
model = Sleep
class DiaryAdmin(NestedModelAdmin):
inlines = [SleepInline]