2010-05-18 6 views
26

Ho un modulo di modifica amministrativa standard per un oggetto, con i soliti moduli StackedInline per una relazione ForeignKey. Vorrei poter collegare ogni elemento in linea al relativo modulo di modifica a dimensione intera, poiché l'elemento in linea contiene elementi in essa contenuti e non riesco a nidificarli.Aggiunta di collegamenti a moduli di modifica completi per elementi in linea nell'amministrazione di django?

Ho provato di tutto, dai widget personalizzati ai modelli personalizzati, e non posso far funzionare nulla. Finora, le "soluzioni" che ho visto sotto forma di frammenti di codice non sembrano funzionare in linea. Mi sto preparando a provare alcuni dom hacking con jQuery solo per farlo funzionare e andare avanti.

Spero di dover perdere qualcosa di molto semplice, in quanto sembra un compito così semplice!

Utilizzo di Django 1.2.

+2

ho trovato la risposta data in http://stackoverflow.com/questions/2120813 meglio. –

+1

Django> = 1,8, usa 'show_change_link' http://stackoverflow.com/a/28170958/3218806 – maxbellec

risposta

11

Ho avuto un problema simile e ho trovato il widget personalizzato più alcune modifiche per modellare la forma. Ecco il widget:

from django.utils.safestring import mark_safe  

class ModelLinkWidget(forms.Widget): 
    def __init__(self, obj, attrs=None): 
     self.object = obj 
     super(ModelLinkWidget, self).__init__(attrs) 

    def render(self, name, value, attrs=None): 
     if self.object.pk: 
      return mark_safe(
       u'<a target="_blank" href="../../../%s/%s/%s/">%s</a>' %\ 
         (
         self.object._meta.app_label, 
         self.object._meta.object_name.lower(), 
         self.object.pk, self.object 
         ) 
      ) 
     else: 
      return mark_safe(u'') 

Ora, poiché widget di per ogni linea bisogno di ottenere oggetto diverso nel costruttore non si può semplicemente impostare in modo standard, ma in init metodo del form:

class TheForm(forms.ModelForm): 
    ... 
    # required=False is essential cause we don't 
    # render input tag so there will be no value submitted. 
    link = forms.CharField(label='link', required=False) 

    def __init__(self, *args, **kwargs): 
     super(TheForm, self).__init__(*args, **kwargs) 
     # instance is always available, it just does or doesn't have pk. 
     self.fields['link'].widget = ModelLinkWidget(self.instance) 

Spero che questo aiuti.

+0

Non ho avuto il tempo di provare questo, ma * sembra * come dovrebbe funzionare. :) Grazie. –

+1

Questa è una soluzione eccellente, può essere resa ancora più bella combinandola con http://stackoverflow.com/questions/5197280/for-a-django-model-how-can-i-get-the-django- admin-url-to-add-another-or-list-o –

+2

Inoltre, questo potrebbe essere vulnerabile agli attacchi XSS (a seconda degli oggetti presentati e da dove provengono), e davvero non li vuoi nell'amministratore - - esegue il rendering della stringa con un modello Django anziché% di python. –

42

ho fatto qualcosa di simile a quanto segue nel mio admin.py:

from django.utils.html import format_html 
from django.core.urlresolvers import reverse 

class MyModelInline(admin.TabularInline): 
    model = MyModel 

    def admin_link(self, instance): 
     url = reverse('admin:%s_%s_change' % (instance._meta.app_label, 
               instance._meta.module_name), 
         args=(instance.id,)) 
     return format_html(u'<a href="{}">Edit</a>', url) 
     # … or if you want to include other fields: 
     return format_html(u'<a href="{}">Edit: {}</a>', url, instance.title) 

    readonly_fields = ('admin_link',) 
+0

L'ho aggiunto al mio amministratore ma non vedo il link. La colonna è stata aggiunta tho. Qualche idea? –

+1

Bella soluzione. Molto pulito – freb

+1

Questa dovrebbe essere la risposta migliore, se funziona. – dspjm

0

penso: args = [instance.id] dovrebbero essere args = [instance.pk]. Ha funzionato per me!

2

risposta di Quentin sopra funziona, ma è anche necessario specificare i campi = ('ADMIN_LINK',)

45

C'è una proprietà chiamata show_change_link dal Django 1.8.

+1

dovrebbe essere la risposta più votata! – rix

+0

Perché questo non è un top? – kotrfa

1

La soluzione attualmente accettata qui è un buon lavoro, ma non è aggiornata.

A partire da Django 1.3, esiste una proprietà incorporata denominata show_change_link = True che risolve questo problema.

Questo può essere aggiunto a qualsiasi oggetto StackedInline o TabularInline. Per esempio:

class ContactListInline(admin.TabularInline): 
    model = ContactList 
    fields = ('name', 'description', 'total_contacts',) 
    readonly_fields = ('name', 'description', 'total_contacts',) 
    show_change_link = True 

Il risultato sarà qualcosa di linea questo:

tabular inline using show_change_link

+0

Ma cosa succede se voglio che un titolo sia un collegamento ipertestuale, ma non un'etichetta accanto al titolo? – adkl