ジャーナル、ボリューム、volume_scanInfoなどのいくつかのモデルを定義しました。
ジャーナルにはより多くのボリュームを含めることができ、ボリュームにはより多くのscanInfoを含めることができます。
私がやりたいことは:
だから私は次のようなものが欲しいです:
Journal #1 admin page
[name]
[publisher]
[url]
.....
list of volumes inline
[volume 10] [..(other fields)..] <a href="/link/to/volume/10">Full record</a>
[volume 20] [..(other fields)..] <a href="/link/to/volume/20">Full record</a>
次に
Volume #20 admin page
[volume number]
[..(other fields)...]
......
list of the scan info inline
[scan info 33] [..(other fields)..] <a href="/link/to/scaninfo/33">Full record</a>
[scan info 44] [..(other fields)..] <a href="/link/to/scaninfo/44">Full record</a>
私がやろうとしたのは、コードを作成するモデルメソッドを定義し、管理者の「ボリュームインライン」を定義するクラス内でそれを使用しようとしたことですが、機能しません。
言い換えると
モデル「Volume」の内部には次のようなものがあります。
def selflink(self):
return '<a href="/admin/journaldb/volume/%s/">Full record</a>' % self.vid
selflink.allow_tags = True
そして
class VolumeInline(admin.TabularInline):
fields = ['volumenumber', 'selflink']
model = Volume
extra = 1
ただし、これにより次のエラーが発生します。
Exception Value: 'VolumeInline.fields' refers to field 'selflink' that is missing from the form.
何か案が?
ありがとう、ジョバンニ
UPDATE:Django 1.8なので、これは組み込まれています。
古い答え:
最後に、私は簡単な解決策を見つけました。
linked.html
のコピーであるtabular.html
という新しいテンプレートを作成し、このコードを追加してリンクを作成しました。
{% if inline_admin_form.original.pk %}
<td class="{{ field.field.name }}">
<a href="/admin/{{ app_label }}/{{ inline_admin_formset.opts.admin_model_path }}/{{ inline_admin_form.original.pk }}/">Full record</a>
</td>
{% endif %}
次に、LinkedInline
を継承する新しいモデルInlineModelAdmin
を作成しました
#override of the InlineModelAdmin to support the link in the tabular inline
class LinkedInline(admin.options.InlineModelAdmin):
template = "admin/linked.html"
admin_model_path = None
def __init__(self, *args):
super(LinkedInline, self).__init__(*args)
if self.admin_model_path is None:
self.admin_model_path = self.model.__name__.lower()
次に、新しいインラインを定義するときに、通常のLinkedInline
の代わりにInlineModelAdmin
を使用するだけで済みます。
他の人にも役立つといいですね。
ジョバンニ
更新:
Django 1.8の時点で、これは 組み込み になりました。
Django <= 1.7:の回答
条件付きの場合、コードをmodels.pyに保持します。
def selflink(self):
if self.id:
return "<a href='/link/to/volume/%s' target='_blank'>Edit</a>" % str(self.id)
else:
return "Not present"
selflink.allow_tags = True
admin.pyで、セルフリンクを 読み取り専用 フィールドとして追加します。
class VolumeInline(admin.TabularInline):
readonly_fields = ['selflink',]
model = Volume
それは私のために働いた。
これは、他のいくつかの回答に基づいた再利用可能なミックスインです。これは、表形式とスタック形式の両方のインラインで機能し、モデルや管理コードを無駄にしないので便利です。
# put this somewhere like admin_helpers.py
from Django.core.urlresolvers import reverse
class InlineEditLinkMixin(object):
readonly_fields = ['edit_details']
edit_label = "Edit"
def edit_details(self, obj):
if obj.id:
opts = self.model._meta
return "<a href='%s' target='_blank'>%s</a>" % (reverse(
'admin:%s_%s_change' % (opts.app_label, opts.object_name.lower()),
args=[obj.id]
), self.edit_label)
else:
return "(save to edit details)"
edit_details.allow_tags = True
# admin.py
class VolumeInline(InlineEditLinkMixin, admin.TabularInline):
fields = ['foo', 'bar', 'edit_details']
class JournalAdmin(admin.ModelAdmin):
inlines = [VolumeInline]
class ScanInfoInline(InlineEditLinkMixin, admin.StackedInline):
fields = ['foo', 'bar', 'edit_details']
class JournalAdmin(admin.ModelAdmin):
inlines = [ScanInfoInline]
Django 1.8+ではこれがはるかに簡単になりました 。次のように、show_change_link = True
をTabularInline
またはStackedInline
サブクラスに追加するだけです。
class VolumeInline(admin.TabularInline):
fields = ['volumenumber']
model = Volume
extra = 1
show_change_link = True
また、モデルに独自の登録済みModelAdmin
がある場合、Djangoは各インラインアイテムの完全な変更フォームへのリンクを自動的に追加します。
管理者URLを逆にする システムを試しましたか?
それは(ジャーナルページで)そのようなものを与える可能性があります:
<ul>
{% for volume in original.volume_set.all %}
<li>
<a href="{% url admin:yourapp_volume_change volume.id %}">Edit {{ volume }}
</a>
</li>
{% endfor %}
</ul>
少しいじった後、reverse()を使用して、InlineAdminとTabularInlineでこれを機能させることができました。少なくともTabularInlineでは、リンクするフィールド必須「readonly_fields」にリストされています
# create a read-only inline with the first field linked
from Django.core import urlresolvers
class YOUR_MODEL_Inline(LinkedTabularInline):
max_num = 0 # remove the "Add another ..." link
model = YOUR_MODEL_NAME
fk_name = "YOUR_FOREIGN_KEY_NAME"
fields = [ 'link_name', ] # , 'field1', 'field2', 'etc' ]
readonly_fields = fields
can_delete = False
def link_name(self, obj):
if obj.pk:
url = urlresolvers.reverse('admin:%s_%s_change'
% (obj._meta.app_label, obj._meta.module_name), args=[obj.id])
# obj.MODEL_FIELD can be a text string or whatever you want
return '<a href="{0}">{1}</a>'.format(url, obj.MODEL_FIELD)
link_name.allow_tags = True
link_name.short_description = "MODEL_FIELD"
変更ビューではなく変更リストにリンクする場合は、reverse()呼び出しを変更できます。チェンジリストにはオブジェクトIDは必要ありません。
url = urlresolvers.reverse('admin:%s_%s_changelist'
% (obj._meta.app_label, obj._meta.module_name))
return '<a href="{0}">{1}</a>'.format(url, obj.name)
また、オブジェクトのサブセットにリンクする場合は、URLにパラメーターを追加できます。
return '<a href="{0}?YOUR_MODEL_FIELD__id__exact={1}">{2}</a>'.format(url, obj.id, obj.name)