53 Stimmen

Django-Admin - Inline-Inlines (oder, drei Modellbearbeitung auf einmal)

Ich habe eine Reihe von Modellen, die so aussehen:

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()

und eine admin.py, die wie folgt aussieht:

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

Mein Ziel ist es, eine Verwaltungsoberfläche zu bekommen, mit der ich alles auf einer Seite bearbeiten kann. Das Endergebnis dieser Modellstruktur ist, dass die Dinge in eine Ansicht+Vorlage generiert werden, die mehr oder weniger wie aussieht:

<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 %}

Ich weiß, dass der inline-in-an-inline-Trick im Django-Admin fehlschlägt, wie ich erwartet hatte. Kennt jemand eine Möglichkeit, diese Art von Modellbearbeitung auf drei Ebenen zu ermöglichen? Vielen Dank im Voraus.

22voto

Matthew Marshall Punkte 5563

Sie müssen eine benutzerdefinierte Formular y Vorlage pour le LinkSectionInline .

So etwas sollte für das Formular funktionieren:

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

(Das ist mir spontan eingefallen und wurde nicht getestet, aber es sollte Sie in die richtige Richtung führen).

Ihre Vorlage muss lediglich das Formular und form.link_formset entsprechend darstellen.

5voto

Ian Price Punkte 7062

Django-verschachtelte Zeilen ist genau für diesen Zweck gebaut. Die Verwendung ist einfach.

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 Punkte 11589

Meine Empfehlung wäre eigentlich, das Modell zu wechseln. Warum haben Sie nicht eine ForeignKey en Link a LinkSection ? Oder, wenn es nicht OneToMany ist, vielleicht ein ManyToMany Feld? Die Verwaltungsschnittstelle wird das kostenlos generieren. Natürlich empfehle ich das nicht, wenn Links logischerweise nichts mit Linkabschnitten zu tun haben, aber vielleicht haben sie das ja? Wenn nicht, erklären Sie bitte, wie die beabsichtigte Organisation aussieht. (Sind zum Beispiel 3 Links pro Abschnitt festgelegt oder willkürlich?)

0voto

pvoosten Punkte 3087

Sie können eine neue Klasse erstellen, ähnlich wie TabularInline oder StackedInline, die selbst Inline-Felder verwenden kann.

Alternativ können Sie auch neue Verwaltungsvorlagen speziell für Ihr Modell erstellen. Aber das setzt natürlich die raffinierten Funktionen der Verwaltungsoberfläche außer Kraft.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X