2010-10-19 13 views
42

Se si desidera eseguire l'override di un modello fornito con un'applicazione in django (in app/templates/app /) si crea un modello con lo stesso nome in un'altra directory, controllato dal caricatore di template prima della dir del modello dell'app. Se si desidera ignorare determinati blocchi del modello, è necessario copiare anche l'intero modello di annuncio che modifica tale blocco, che in realtà non è molto ASCIUTTO.Django: sostituzione e estensione di un modello di app

Qualcuno conosce un modo per sovrascrivere il modello originale, mentre nello stesso momento lo estende, in modo tale che è sufficiente sovrascrivere il blocco specifico che si desidera modificare? (La cosa sta facendo questo senza cambiare il nome del modello, perché in alcuni casi potrebbe essere necessario modificare la visualizzazione per farlo funzionare con un altro modello)

EDIT: Come Adam Taylor ha sottolineato nei commenti da Django 1.9 on questo è possibile senza alcun hack.

+0

@paulo: per quanto ne so ci sono naturalmente documenti circa sovrascrivendo i modelli della app in generale, in quanto questo è pratica quotidiana, ma non ho mai visto niente sull'estensione di un modello che ha lo stesso nome. Se sai che è nei documenti per favore indicami quel posto ... –

+0

http://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing-an-admin-template –

+1

L'approccio qui funziona solo per i modelli di amministrazione specifici dell'app, poiché questi si spostano su un percorso diverso rispetto all'originale.Questa è la ragione per cui questo è nel documento * admin * e non in quello generale;) –

risposta

34

Penso che la risposta da this related question sia pertinente; al momento, la soluzione migliore sembra essere l'utilizzo di un caricatore di modelli personalizzato da django-apptemplates package on PyPI, quindi è sufficiente utilizzare pip per installarlo (ad esempio pip install django-apptemplates).

Il caricatore di modelli consente di estendere un modello in un'app specifica; per esempio, di estendere la pagina indice del inteface admin, si dovrebbe aggiungere

'apptemplates.Loader', 

alla tua lista TEMPLATE_LOADERS in settings.py, e utilizzare

{% extends "admin:admin/index.html" %} 

nei vostri modelli.

+1

Un progetto su cui sto utilizzando lo snippet per risolvere questo problema esatto. Sono sorpreso che più persone non lo colpiscano: un'app che vuole modificare parti di pagine esistenti. –

+2

Penso che questo sia un problema comune, ma le persone lo fanno grazie alla duplicazione di modelli completi. Se qualcuno ha provato, la sovrascrittura e l'estensione spesso si concludono con una ricorsione infinita. Il problema è descritto in questo ticket: https://code.djangoproject.com/ticket/15053 – Nagyman

-1

[update]

Ho letto male la domanda, la mia risposta originale si applica solo al app di amministrazione, che ha un meccanismo di estensione modello di built-in. Per le altre app che mancano di tale meccanismo, dovrei semplicemente forgiare i modelli originali invece di giocherellare con i caricatori di modelli personalizzati come la risposta scelta consiglia. Se sei preoccupato di biforcarsi, puoi anche implementare un meccanismo di estensione e contribuire al progetto originale se pensi che valga la pena.


[risposta originale]

Direttamente dal bel manual: Grazie alla struttura modulare dei modelli di amministrazione, di solito è necessario né consigliabile sostituire un intero modello. È quasi sempre preferibile sovrascrivere solo la sezione del modello che è necessario modificare.

Per continuare l'esempio sopra, vogliamo aggiungere un nuovo collegamento accanto allo strumento Cronologia per il modello di pagina. Dopo aver esaminato change_form.html, stabiliamo che dobbiamo solo sovrascrivere il blocco degli oggetti-strumenti. Ecco quindi il nostro nuovo change_form.html:

{% extends "admin/change_form.html" %} 
{% load i18n %} 
{% block object-tools %} 
{% if change %}{% if not is_popup %} 
    <ul class="object-tools"> 
    <li><a href="history/" class="historylink">{% trans "History" %}</a></li> 
    <li><a href="mylink/" class="historylink">My Link</a></li> 
    {% if has_absolute_url %} 
     <li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink"> 
      {% trans "View on site" %}</a> 
     </li> 
    {% endif%} 
    </ul> 
{% endif %}{% endif %} 
{% endblock %} 

E il gioco è fatto! Se abbiamo inserito questo file nella directory templates/admin/my_app, il nostro link comparirà sul modulo di modifica di ogni modello.

+0

Grazie per aver postato questo, ma la mia domanda non riguarda i modelli ADMIN. Sto cercando di fare qualcosa del genere con i modelli (frontend) che ad es. vieni con un'applicazione di terze parti, dove probabilmente voglio solo cambiare un blocco, e copiare tutto il resto per scavalcare solo una parte mi sembra una violazione DRY ... –

+1

@lazerscience: è lo stesso processo, tranne che nel tuo modello directory dovresti rispettare la stessa struttura di directory dei modelli che stai sovrascrivendo. Controllare: http://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loader.select_template –

+4

Non penso che questo risponda ancora alla domanda originale. Supponi che 'niceapp.views.index()' usi il template 'niceapp/index.html'. Se voglio usare la vista originale ma personalizzare il modello, posso creare un 'niceapp/index.html' in una directory' templates' del mio progetto o della mia app. Ma come estendere l'originale e sovrascrivere solo alcuni blocchi e non copiare l'intero modello? Dire "{% estendere" niceapp/index.html "%}" a quanto pare non fa il lavoro. – akaihola

2

Nella wiki Django, Simon Willison presenta a trick per ottenere l'effetto "modello autoestinguente". Non è direttamente applicabile se si sta utilizzando il caricatore di modelli app_directories.

Il collegamento di directory di modelli di app all'interno di una nuova directory potrebbe essere un trucco.

+0

Grazie, anche questo non è al 100% quello che stavo cercando, ma non credo che tu possa avvicinarti di più; stava già facendo qualcosa di simile durante la personalizzazione di templatesd per diversi siti! –

-3

Un modo semplice per farlo è questo:

Diciamo che si desidera estendere e sovrascrivere Django/contrib/admin/templates/admin/change_form.html.

Innanzitutto, copia il file change_form.html originale nella directory del modello della tua app e rinominalo come myapp/templates/admin/original_change_form.html. (Puoi anche farlo come link simbolico.)

In secondo luogo, crea il tuo change_form.html in myapp/templates/admin. Nella parte superiore, inserisci quanto segue:

{% extends "admin/original_change_form.html" %} 

Semplice!

+0

In realtà non è una soluzione sbagliata, specialmente se il tuo sistema supporta i collegamenti simbolici. – Flimm

6

Come aggiornamento poiché questa sembra essere una domanda popolare. Ho usato il overextends app senza alcun problema. Fornisce una nuova parola chiave overestend che consente di estendere modelli con lo stesso nome.

Ed è facile da installare con pip:

pip install -U django-overextends 
+0

wow, questo è super facile e leggero! lo adoro! Grazie! –

+0

FYI L'ultima versione per Django 1.4 era 0.3.2, questi ultimi hanno bisogno di 1.7 –

3

Django 1.9 e più tardi ha this feature:

Django caricatori template possono ora estendere i modelli in modo ricorsivo.

modo da poter avere un file da app1 con contenuti in questo modo:

app1/templates/example/foobar.html:

<p>I'm from app1</p> 
{% block main %}{% endblock %} 

E qui può allungare con un file da app2 (notare che il nome del modello example/foobar.html è lo stesso):

app2/templates/example/foobar.html:

{% extends "example/foobar.html" %} 
{% block main %} 
    <p>I'm from app2</p> 
{% endblock %} 

Il risultato finale dovrebbe essere:

<p>I'm from app1</p> 
<p>I'm from app2</p> 
+0

Ho provato esattamente questa configurazione e non sembra funzionare. – HoHo

+0

@HoHo quale versione di Django stai usando? – Flimm

+0

Sto usando 1.10 - se 'app1' ha un insieme di modelli interconnessi (ad esempio' app1/templates/app1/base.html', che è esteso da 'app1/templates/app1/subfolder/subsite.html') , come dovrebbero i modelli 'app2' estendere entrambi questi modelli? Ho capito che usare il tuo metodo - dove si replica la gerarchia di cartelle e i nomi di file in "app1" - funzionerebbe, ma non sembra. – HoHo

Problemi correlati