Il me faut un administrateur imbriqué Django en ligne, Auquel je peux inclure le champ de date en ligne dans un autre en ligne comme ci-dessous.
J'ai les modèles ci-dessous:
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)
et l'administrateur ci-dessous:
class CertificateInline(admin.StackedInline):
model = Certificate
class PersonAdmin(admin.ModelAdmin):
inlines = [CertificateInline,]
admin.site.register(Person,PersonAdmin)
mais je dois inclure le modèle Training_Date en ligne, qui fait partie de Certificate admin inline.
Une idée ?
Autant que je sache, vous ne pouvez pas avoir un deuxième niveau d'inlines dans l'administrateur Django par défaut.
L'administrateur Django est juste une application Django normale, rien ne vous empêche donc d'implémenter un deuxième niveau de formulaires imbriqués, mais à mon humble avis, ce serait une sorte de conception compliquée à mettre en œuvre. C’est peut-être pour cette raison que rien n’est prévu.
Il y a eu un mouvement dans https://code.djangoproject.com/ticket/9025 récemment, mais je ne pouvais pas retenir mon souffle.
Une solution courante consiste à créer un lien entre un premier et un deuxième (ou un deuxième et un troisième) administrateurs en ayant à la fois un ModelAdmin et un Inline pour le même modèle:
Attribuez à ModelAdmin un certificat avec TrainingDate en ligne. Attribuez à CertificateInline un champ "Détails" supplémentaire, qui est un lien vers son formulaire de modification 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)
Solution plus universelle
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)
pip install Django-nested-inline
Ce paquet devrait faire ce dont vous avez besoin.
Les inlines imbriquées sont fournies à l'adresse suivante: https://github.com/BertrandBordage/Django-super-inlines/
pip install Django-super-inlines
J'ai utilisé la solution fournie par @bigzbig (merci).
Je voulais aussi revenir à la première page de la liste une fois les modifications sauvegardées, alors ajouté:
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))