web-dev-qa-db-ja.com

Django Adminネストされたインライン

入れ子になったDjango adminインラインが必要です。これは、以下のような他のインラインに日付フィールドインラインを含めることができます。

私は以下のモデルを持っています:

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モデルを含める必要があります。

何か案が ?

45
tunaktunak

知る限りでは、デフォルトのDjango= admin。

Django adminは単なる通常のDjangoアプリケーションであるため、ネストされたフォームの第2レベルの実装を妨げるものは何もありませんが、IMHOは一種の複雑なものになりますおそらく、それが提供されない理由です。

11
Paulo Scardine

https://code.djangoproject.com/ticket/9025 にはいくつかの動きがありましたが、息を止めません。

これを回避する一般的な方法の1つは、同じモデルのModelAdminとInlineの両方を使用して、1番目と2番目(または2番目と3番目)のレベル間で管理者にリンクすることです。

TrainingDateをインラインとして証明書をModelAdminに提供します。 ModelInchangeフォームへのリンクである追加フィールド「Details」にCertificateInlineを指定します。

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)
34
Danny W. Adair

より普遍的なソリューション

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)
18
bigzbig
pip install Django-nested-inline

このパッケージは必要なことを行う必要があります。

11
s-block

ネストされたインラインは次の場所で提供されます: https://github.com/BertrandBordage/Django-super-inlines/

pip install Django-super-inlines
4
Rick Westera

@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))
2