是否可以手动指定要在内联中显示的相关对象集,其中不存在外键关系?
# 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
模型管理员显示Sleep
模型的内联,其中start_time
等于与Diary.day
相同的日期。问题是Sleep
模型没有ForeignKey
到Diary
(相反,使用日期隐含了这种关系)。
使用上面的内容,Django立即抱怨
<class 'records.admin.SleepInline'>: (admin.E202) 'records.Sleep' has no ForeignKey to 'records.Diary'.
如何在Sleep
管理页面上将相关Diary
个实例显示为内联?
答案 0 :(得分:5)
Django管理员内联是围绕ForeignKey
字段(或ManyToManyField
,OneToOneField
)构建的。但是,如果我了解您的目标,就必须避免必须管理&#34;日期完整性&#34;您的Diary.day
和Sleep.start_time
字段之间的关系,即当该关系确实由Diary.day == Sleep.start_time.date()
Django ForiegnKey
字段有to_field property,允许FK索引除id
之外的列。但是,由于DateTimeField
中有Sleep
,DateField
中有Diary
,我们需要将DateTimeField
分开。此外,ForeignKey
必须与&#34; 1&#34;关系的一面。需要设置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管理员也是您期望的,并且避免了&#34;日期冗余&#34;:
提前考虑更真实(和有问题的)用例,假设每个用户每天可以有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和其他SQL DBMS中允许使用复合外键。我从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一开始看起来很有趣,但并没有创造出真正的&#34;复合外键,也不适用于Django的管理员。
答案 1 :(得分:2)
首先让我向您展示您逻辑的缺点:
您注意到的另一个缺点是您无法使用关系功能。 InlineAdmin是一个关系功能,所以就像你说“让管理工作”一样,你真的要求用锤子拧开螺栓。
但是......管理员使用了ModelForm。因此,如果您使用formset构造表单(由于同样的原因,它不能是内联formset)并且自己处理保存该表单集,那么它应该是可能的。 InlineFormset和InlineAdmin的重点是使相关模型的formset生成更容易,并且需要知道关系。
最后,您可以add urls构建自定义页面,在扩展admin / base.html模板时,您可以访问布局和javascript组件。
答案 2 :(得分:0)
您可以使用Nested_admin库实现此目的。所以myapp / admin.py
from nested_admin.nested import NestedStackedInline, NestedModelAdmin
class SleepInline(NestedStackedInline):
model = Sleep
class DiaryAdmin(NestedModelAdmin):
inlines = [SleepInline]