【问题标题】:Django Admin nested inlineDjango Admin 嵌套内联
【发布时间】:2023-03-20 19:50:02
【问题描述】:

我需要一个嵌套的 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 模型作为内联包含在内,这是证书管理内联的一部分。

有什么想法吗?

【问题讨论】:

    标签: django django-models django-admin


    【解决方案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

    更新(2022 年 1 月 25 日): 这是文档中的更新链接(Django 4.0):https://docs.djangoproject.com/en/4.0/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.show_change_link

    【讨论】:

      【解决方案2】:

      https://code.djangoproject.com/ticket/9025最近有一些动静,但我不会屏住呼吸。

      解决此问题的一种常见方法是通过为同一模型同时拥有 ModelAdmin 和内联来链接到第一和第二(或第二和第三)级别之间的管理员:

      Certificate 一个ModelAdminTrainingDate 作为内联。为CertificateInline 提供一个附加字段“详细信息”,该字段是指向其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)
      

      【讨论】:

      • 这是一个不错的解决方案。我想指出您可以将changeform_link 放在CertificateLinkInline 中。那可能是一个更好的地方,因为它是 django-admin 特定的。请注意,当您这样做时,您应该使用instance.id 而不是self.id 来访问模型的实例。见docs.djangoproject.com/en/dev/ref/contrib/admin/…
      • 如果 changeform_link 方法产生异常,那么 django 将吃掉它并继续,将字段留空。我永远无法找到 django 将回溯放在哪里,或者它是否对它做了任何事情。我建议将其包装在 try/except 中,以确保在某处记录异常。为简化起见,创建一个装饰器来处理所有这些可能会很有用。
      • 看起来在 Django 2+ 上,您只需将 show_change_link = True 添加到您的 admin.TabularInline 类,我认为只要您也有一个常规的 admin.ModelAdmin ,它就会显示“更改” 内联中的链接。
      • 哇?,完美的解决方案。
      • 虽然使用show_change_link = True 要简单得多。
      【解决方案3】:

      更通用的解决方案

      from django.utils.safestring import mark_safe
      from django.urls 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)
      

      【讨论】:

      【解决方案4】:

      我使用了@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))
      

      【讨论】:

      • 感谢sn-p!我只是想补充一点,这仅在 MyModelAdmin 中包含 post_save_change 函数后才对我有用。
      【解决方案5】:

      嵌套内联在以下位置提供: https://github.com/BertrandBordage/django-super-inlines/

      pip install django-super-inlines
      

      【讨论】:

      • 我试过了。它不允许我添加或删除一些内联,并迫使我制作 3 个新的子对象。在这个开发阶段它不可用。
      【解决方案6】:
      pip install django-nested-inline
      

      这个包应该能满足你的需要。

      【讨论】:

      • django-nested-inline 在最新的 django 版本上(还没有?)支持。但是你可以考虑使用github.com/theatlantic/django-nested-admin,这几乎是一样的。
      • @vmonteco 你能给我一个文档链接吗,其中描述了如何在没有包的情况下使用它?
      • @OleksandrDashkov django-nested-admin.readthedocs.io/en/latest,在 github 页面的顶部。但可能仍然需要安装软件包。
      • 警告,我开始使用 django-nested-inline 并且遇到了多个错误,这些错误需要很长时间才能弄清楚。在决定使用哪个模块之前,您可能需要评估其他选项。
      • @pspahn 你有没有找到任何合理的替代方案
      【解决方案7】:

      AFAIK,您不能在默认的 Django 管理员中拥有第二级内联。

      Django admin 只是一个普通的 Django 应用程序,所以没有什么能阻止您实现第二级嵌套表单,但恕我直言,这将是一种复杂的实现设计。也许这就是为什么没有提供它的原因。

      【讨论】:

      • 我面临着类似的情况。我想我将覆盖内联模板并添加一些链接到第二级。
      猜你喜欢
      • 1970-01-01
      • 2022-06-25
      • 2019-06-07
      • 2015-04-28
      • 1970-01-01
      • 2011-05-02
      • 2016-04-07
      • 2011-02-23
      • 2020-04-16
      相关资源
      最近更新 更多