51 votes

Django admin - inline inlines (ou, trois éditions de modèles à la fois)

J'ai un ensemble de modèles qui ressemblent à ça :

class Page(models.Model):
    title = models.CharField(max_length=255)

class LinkSection(models.Model):
    page = models.ForeignKey(Page)
    title = models.CharField(max_length=255)

class Link(models.Model):
    linksection = models.ForeignKey(LinkSection)
    text = models.CharField(max_length=255)
    url = models.URLField()

et un admin.py qui ressemble à ça :

class LinkInline(admin.TabularInline):
    model = Link
class LinkSectionInline(admin.TabularInline):
    model = LinkSection
    inlines = [ LinkInline, ]
class PageAdmin(admin.ModelAdmin):
    inlines = [ LinkSectionInline, ]

Mon objectif est d'obtenir une interface d'administration qui me permette de tout modifier sur une seule page. Le résultat final de cette structure de modèle est que les choses sont générées dans une vue + modèle qui ressemble plus ou moins à :

<h1>{{page.title}}</h1>
{% for ls in page.linksection_set.objects.all %}
<div>
    <h2>{{ls.title}}</h2>
    <ul>
         {% for l in ls.link_set.objects.all %}
        <li><a href="{{l.url}}">{{l.title}}</a></li>
         {% endfor %}
    </ul>
</div>
{% endfor %}

Je sais que l'astuce inline-in-an-inline échoue dans l'administration de Django, comme je m'y attendais. Quelqu'un connaît-il un moyen d'autoriser ce type d'édition de modèle à trois niveaux ? Merci d'avance.

22voto

Matthew Marshall Points 2521

Vous devez créer un formulaire y modèle pour le LinkSectionInline .

Quelque chose comme ceci devrait fonctionner pour le formulaire :

LinkFormset = forms.modelformset_factory(Link)
class LinkSectionForm(forms.ModelForm):
    def __init__(self, **kwargs):
        super(LinkSectionForm, self).__init__(**kwargs)
        self.link_formset = LinkFormset(instance=self.instance, 
                                        data=self.data or None,
                                        prefix=self.prefix)

    def is_valid(self):
        return (super(LinkSectionForm, self).is_valid() and 
                    self.link_formset.is_valid())

    def save(self, commit=True):
        # Supporting commit=False is another can of worms.  No use dealing
        # it before it's needed. (YAGNI)
        assert commit == True 
        res = super(LinkSectionForm, self).save(commit=commit)
        self.link_formset.save()
        return res

(Cette liste est sortie tout droit de ma tête et n'a pas été testée, mais elle devrait vous permettre d'avancer dans la bonne direction).

Votre modèle doit simplement rendre le formulaire et le form.link_formset de manière appropriée.

5voto

Ian Price Points 4136

Django-nested-inlines est conçu pour cela. L'utilisation est simple.

from django.contrib import admin
from nested_inlines.admin import NestedModelAdmin, NestedStackedInline, NestedTabularInline
from models import A, B, C

class MyNestedInline(NestedTabularInline):
    model = C

class MyInline(NestedStackedInline):
    model = B
    inlines = [MyNestedInline,]

class MyAdmin(NestedModelAdmin):
    pass

admin.site.register(A, MyAdmin)

1voto

David Berger Points 5459

Ma recommandation serait en fait de changer de modèle. Pourquoi ne pas avoir un ForeignKey sur Link a LinkSection ? Ou, si ce n'est pas un OneToMany, peut-être un ManyToMany champ ? L'interface d'administration le génère gratuitement. Bien sûr, je ne le recommande pas si les liens n'ont logiquement rien à voir avec les sections de liens, mais peut-être que c'est le cas ? Si ce n'est pas le cas, veuillez expliquer quelle est l'organisation prévue. (Par exemple, est-ce que 3 liens par section est fixe ou arbitraire).

0voto

pvoosten Points 1684

Vous pouvez créer une nouvelle classe, similaire à TabularInline ou StackedInline, capable d'utiliser elle-même les champs en ligne.

Vous pouvez également créer de nouveaux modèles d'administration, spécifiquement pour votre modèle. Mais cela annule bien sûr les fonctionnalités intéressantes de l'interface d'administration.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X