Добавление ссылок на полные формы изменений для встроенных элементов в django admin? - PullRequest
34 голосов
/ 18 мая 2010

У меня есть стандартная форма смены администратора для объекта с обычными формами StackedInline для отношения ForeignKey. Я хотел бы иметь возможность связать каждый встроенный элемент с соответствующей полноразмерной формой изменения, поскольку встроенный элемент имеет собственные встроенные элементы, и я не могу их вложить.

Я перепробовал все, от пользовательских виджетов до пользовательских шаблонов, и не могу заставить что-либо работать. Пока что «решения», которые я видел в виде фрагментов, просто не работают для встроенных строк. Я собираюсь попробовать взломать DOM с помощью jQuery, чтобы заставить его работать и двигаться дальше.

Надеюсь, мне не хватает чего-то очень простого, так как это кажется такой простой задачей!

Использование Django 1.2.

Ответы [ 6 ]

75 голосов
/ 27 января 2015

Существует свойство с именем show_change_link, начиная с Django 1.8.

44 голосов
/ 24 февраля 2013

Я сделал что-то подобное в моем 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',)
11 голосов
/ 28 мая 2010

У меня была похожая проблема, и я придумал собственный виджет плюс несколько настроек для формы модели. Вот виджет:

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

Теперь, поскольку виджет для каждого встроенного элемента должен получать разные объекты в конструкторе, вы не можете просто установить его стандартным способом, но в методе init формы:

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)

Надеюсь, это поможет.

9 голосов
/ 22 января 2018

В настоящее время здесь принято хорошее решение, но оно устарело.

Начиная с Django 1.3, существует встроенное свойство show_change_link = True, которое решает эту проблему.

Это можно добавить к любому объекту StackedInline или TabularInline. Например:

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

В результате будет получена следующая строка:

tabular inline using show_change_link

2 голосов
/ 26 марта 2014

Ответ Квентина выше работает, но вам также нужно указать поля = ('admin_link',)

0 голосов
/ 15 апреля 2013

Я думаю: args = [instance.id] должно быть args = [instance.pk]. У меня это сработало!

...