我需要一个嵌套的django admin inline, 我可以在下面的其他内联中包含日期字段内联。
我有以下模型:
class Person(models.Model):
name = models.CharField(max_length=200)
id_no = models.IntegerField()
class Certificate(models.Model):
cerfificate_no = models.CharField(max_length=200)
certificate_date = models.DateField(max_length=100)
person = models.ForeignKey(Person)
training = models.CharField(max_length=200)
class Training_Date(models.Model):
date = models.DateField()
certificate = models.ForeignKey(Certificate)
和以下管理员:
class CertificateInline(admin.StackedInline):
model = Certificate
class PersonAdmin(admin.ModelAdmin):
inlines = [CertificateInline,]
admin.site.register(Person,PersonAdmin)
但我需要将Training_Date模型包含在内联中,这是证书管理员内联的一部分。
有什么想法吗?
答案 0 :(得分:34)
最近https://code.djangoproject.com/ticket/9025发生了一些变动,但我不会屏住呼吸。
一种常见的方法是通过为同一模型同时使用ModelAdmin和Inline来链接到第一和第二(或第二和第三)级别之间的管理员:
将CertificateDate作为内联的证书提供给ModelAdmin。为CertificateInline提供一个附加字段“Details”,它是ModelAdmin更改表单的链接。
models.py:
from django.core import urlresolvers
class Certificate(models.Model):
# ...
def changeform_link(self):
if self.id:
# Replace "myapp" with the name of the app containing
# your Certificate model:
changeform_url = urlresolvers.reverse(
'admin:myapp_certificate_change', args=(self.id,)
)
return u'<a href="%s" target="_blank">Details</a>' % changeform_url
return u''
changeform_link.allow_tags = True
changeform_link.short_description = '' # omit column header
admin.py:
# Certificate change form has training dates as inline
class TrainingDateInline(admin.StackedInline):
model = TrainingDate
class CertificateAdmin(admin.ModelAdmin):
inlines = [TrainingDateInline,]
admin.site.register(Certificate ,CertificateAdmin)
# Person has Certificates inline but rather
# than nesting inlines (not possible), shows a link to
# its own ModelAdmin's change form, for accessing TrainingDates:
class CertificateLinkInline(admin.TabularInline):
model = Certificate
# Whichever fields you want: (I usually use only a couple
# needed to identify the entry)
fields = ('cerfificate_no', 'certificate_date', 'changeform_link')
readonly_fields = ('changeform_link', )
class PersonAdmin(admin.ModelAdmin):
inlines = [CertificateLinkInline,]
admin.site.register(Person, PersonAdmin)
答案 1 :(得分:17)
更通用的解决方案
from django.utils.safestring import mark_safe
from django.core.urlresolvers import reverse
class EditLinkToInlineObject(object):
def edit_link(self, instance):
url = reverse('admin:%s_%s_change' % (
instance._meta.app_label, instance._meta.model_name), args=[instance.pk] )
if instance.pk:
return mark_safe(u'<a href="{u}">edit</a>'.format(u=url))
else:
return ''
class MyModelInline(EditLinkToInlineObject, admin.TabularInline):
model = MyModel
readonly_fields = ('edit_link', )
class MySecondModelAdmin(admin.ModelAdmin):
inlines = (MyModelInline, )
admin.site.register(MyModel)
admin.site.register(MySecondModel, MySecondModelAdmin)
答案 2 :(得分:10)
AFAIK,你不能在默认的Django管理员中拥有第二级内联。
Django管理员只是一个普通的Django应用程序,所以没有什么能阻止你实现第二级嵌套表单,但恕我直言,这将是一种复杂的设计来实现。也许这就是没有规定的原因。
答案 3 :(得分:10)
pip install django-nested-inline
这个包应该做你需要的。
答案 4 :(得分:4)
嵌套内联提供于: https://github.com/BertrandBordage/django-super-inlines/
pip install django-super-inlines
答案 5 :(得分:2)
我使用了@bigzbig提供的解决方案(谢谢)。
我还想在保存更改后返回第一个列表页面,这样就添加了:
class MyModelInline(EditLinkToInlineObject, admin.TabularInline):
model = MyModel
readonly_fields = ('edit_link', )
def response_post_save_change(self, request, obj):
my_second_model_id = MyModel.objects.get(pk=obj.pk).my_second_model_id
return redirect("/admin/mysite/mysecondmodel/%s/change/" % (my_second_model_id))
答案 6 :(得分:1)
更新的解决方案(2021 年 2 月)是使用 show_change_link 配置变量:https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.show_change_link
这与上述解决方案中提出的 EditLinkToInlineObject 完全相同,但代码更少,并且可能已经过 Django 开发人员的良好测试
您只需在每个内联中定义 show_change_link=True