2010-05-18 3 views
26

Ich habe ein Standard-Admin-Änderungsformular für ein Objekt mit den üblichen StackedInline-Formularen für eine ForeignKey-Beziehung. Ich möchte in der Lage sein, jeden Inline-Artikel mit dem entsprechenden Änderungsformular in voller Größe zu verknüpfen, da der Inline-Artikel eigene Elemente enthält und ich sie nicht verschachteln kann.Hinzufügen von Links zu vollständigen Änderungsformularen für Inline-Elemente in django admin?

Ich habe alles von benutzerdefinierten Widgets zu benutzerdefinierten Vorlagen versucht, und kann nichts machen. Bisher scheinen die "Lösungen", die ich in Form von Schnipsel gesehen habe, einfach nicht für Inlines zu funktionieren. Ich bereite mich darauf vor, DOM-Hacking mit jQuery zu versuchen, nur um es zum Laufen zu bringen.

Ich hoffe, ich muss etwas sehr einfaches vermissen, wie dies scheint so eine einfache Aufgabe!

Verwenden von Django 1.2.

+2

Ich fand das in http://stackoverflow.com/questions/2120813 besser gegebene Antwort:

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

Das Ergebnis wird dies etwas Linie sein. –

+1

Django> = 1.8, benutze 'show_change_link' http://stackoverflow.com/a/28170958/3218806 – maxbellec

Antwort

11

Ich hatte ähnliches Problem und ich kam mit benutzerdefinierten Widget plus einige Verbesserungen an Modellform. Hier ist das 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'') 

Da nun Widget für jede Inline benötigt unterschiedliches Objekt im Konstruktor bekommen kann man nicht einfach es in üblichen Weise festgelegt, aber in Formular init Methode:

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) 

Ich hoffe das hilft.

+0

Ich hatte noch keine Zeit, dies zu versuchen, aber es * sieht aus * wie es funktionieren sollte. :) Vielen Dank. –

+1

Dies ist eine feine Lösung, sie kann noch feiner gemacht werden, indem sie mit http://stackoverflow.com/questions/5197280/for-a-django-model-how-can-i-get-the-django- kombiniert wird. admin-url-to-add-another-or-list-o –

+2

Auch dies kann anfällig für XSS-Angriffe sein (abhängig von den Objekten präsentiert und woher sie kommen), und Sie wollen wirklich nicht diejenigen im Admin - - render die Zeichenfolge mit einer Django-Vorlage anstelle von%. –

42

Ich habe so etwas wie die folgenden in meinem 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

Ich habe dies zu meinem Admin hinzugefügt, aber ich sehe den Link nicht. Die Spalte wurde hinzugefügt. Irgendwelche Ideen? –

+1

Schöne Lösung. Sehr sauber – freb

+1

Dies sollte die beste Antwort sein, wenn es funktioniert. – dspjm

0

Ich denke: args = [instance.id] sollte args = [instance.pk] sein. Es hat für mich funktioniert!

2

Quentin Antwort oben genannten Arbeiten, aber Sie müssen auch Felder angeben = ('ADMIN_LINK')

45

Es ist eine Eigenschaft show_change_link seit Django 1.8 genannt.

+1

sollte die am besten gewählte Antwort sein! – rix

+0

Warum ist das kein Top? – kotrfa

1

Die derzeit akzeptierte Lösung ist gute Arbeit, aber es ist veraltet.

Seit Django 1.3 gibt es eine integrierte Eigenschaft namens show_change_link = True, die dieses Problem anspricht.

Dies kann zu jedem StackedInline- oder TabularInline-Objekt hinzugefügt werden. Zum Beispiel:

tabular inline using show_change_link

+0

Aber was, wenn ich möchte, dass ein Titel ein Hyperlink ist, aber kein Etikett neben dem Titel? – adkl

Verwandte Themen