2009-03-31 8 views
51

Ho un insieme di modelli che assomigliano a questo:Django admin - inline in linea (o, a tre la modifica del modello in una sola volta)

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

e un admin.py che assomiglia a questo:

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

Il mio obiettivo è ottenere un'interfaccia di amministrazione che mi permetta di modificare tutto su una pagina. Il risultato finale di questa struttura del modello è che le cose sono generati in una visione + modello che sembra più o meno come:

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

So che il trucco inline-in-un-linea non riesce a admin Django, come Mi aspettavo Qualcuno sa di un modo per consentire questo tipo di editing di modelli a tre livelli? Grazie in anticipo.

+3

Potrebbe mostrare il codice finale con la soluzione che hai accettato? –

risposta

20

È necessario creare un numero personalizzato form e template per il LinkSectionInline.

Qualcosa del genere dovrebbe funzionare per la forma:

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 

(che è appena uscito fuori dalla parte superiore della mia testa e non è testato, ma dovrebbe farti andare nella giusta direzione.)

Il modello deve solo rendere il modulo e form.link_formset in modo appropriato.

+7

Possiamo ottenere codice modello di esempio per questa risposta? È consigliabile inserire il file change_form.html di Django per questo? Inoltre, in Django 1.2.3, la prima riga dovrebbe essere LinkFormSet = forms.inlineformset_factory (Link) – Bluu

+3

Ciao sto cercando di farlo funzionare ma sto ottenendo errori con LinkFormset che non vuole prendere istanza = self.instance, eventuali raccomandazioni – Hugoagogo

+1

Idea brillante per annidare il formset nel modulo. Testeremo che :-) – vdboor

1

La mia raccomandazione sarebbe in realtà di cambiare il modello. Perché non avere unin Link a LinkSection? Oppure, se non è OneToMany, forse un campo ManyToMany? L'interfaccia di amministrazione la genererà gratuitamente. Naturalmente, non consiglio questo se i collegamenti non hanno logicamente nulla a che fare con le sezioni dei collegamenti, ma forse lo fanno? In caso contrario, si prega di spiegare che cos'è l'organizzazione prevista. (Ad esempio, 3 collegamenti per sezione sono fissi o arbitrari?)

+0

Sciocco, ho omesso il campo ForeignKey che intendevo essere lì :). I collegamenti hanno a che fare con le sezioni di collegamento (intese come intestazione di sorta). I 3 collegamenti per sezione sono arbitrari. Modificherò l'OP per riflettere meglio questo. –

0

È possibile creare una nuova classe, simile a TabularInline o StackedInline, che è in grado di utilizzare i campi incorporati.

In alternativa, è possibile creare nuovi modelli di amministrazione, in particolare per il modello. Ma questo ovviamente sovrascrive le eleganti funzionalità dell'interfaccia di amministrazione.

4

Django-nested-inlines è stato creato proprio per questo. L'utilizzo è semplice

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)