Django管理者リストの表示でオブジェクトのリンクを変更しようとしています。これまでのところ、次のようになっています。
class FooModelAdmin(admin.ModelAdmin):
fields = ('foo','bar')
list_display = ('foo_link','bar')
def foo_link(self,obj):
return u'<a href="/foos/%s/">%s</a>' % (obj.foo,obj)
domain_link.allow_tags = True
domain_link.short_description = "foo"
これにより、元のリスト表示リンク内に別のリンクが生成されます。
<a href="/admin/app/model/pk/"><a href="/foos/foo/">Foo</a></a>
解決策は、initをオーバーライドし、list_display_linksをNoneに設定することでした。
class FooModelAdmin(admin.ModelAdmin):
fields = ('foo','bar')
list_display = ('foo_link','bar')
def foo_link(self,obj):
return u'<a href="/foos/%s/">%s</a>' % (obj.foo,obj)
foo_link.allow_tags = True
foo_link.short_description = "foo"
def __init__(self,*args,**kwargs):
super(FooModelAdmin, self).__init__(*args, **kwargs)
self.list_display_links = (None, )
それを行う正しい方法は、ChangeListをサブクラス化し、url_for_resultメソッドをオーバーライドして、必要な正しい変更URLを作成することだと思います。
Admin.ModelAdminサブクラスのget_changelistをオーバーライドして、新しいクラスを返します。
from Django.contrib.admin.views.main import ChangeList
from Django.contrib.admin.util import quote
class FooChangeList(ChangeList):
def url_for_result(self, result):
pk = getattr(result, self.pk_attname)
return '/foos/foo/%d/' % (quote(pk))
class FooAdmin(admin.ModelAdmin):
def get_changelist(self, request, **kwargs):
return FooChangeList
デフォルトでは、リスト表示の最初の列は管理者編集ページにリンクされます。別の列をそのリンクにしたい場合、非常に簡単な方法は次のとおりです。
class FooModelAdmin(admin.ModelAdmin):
list_display = ('foo_link', 'bar', 'another_bar', )
list_display_links = ('foo_link', 'another_bar', )
foo_link
がモデルのプロパティでない場合は、次のように呼び出すことができます。
class FooModelAdmin(admin.ModelAdmin):
list_display = ('foo_link', 'bar', 'another_bar', )
list_display_links = ('foo_link', 'another_bar', )
def foo_link(self, obj):
return "%s blah blah" % obj.some_property # or anything you prefer e.g. an edit button
私のプロジェクトからの完全な例:
class SchoolTeacherAdmin(admin.ModelAdmin):
list_display = ('name', 'designation', 'school_name', 'school_code', 'date_of_birth', 'mobile', 'nid', 'edit', )
list_display_links = ('edit', )
def school_code(self, obj):
return obj.school.code
def school_name(self, obj):
return obj.school.name.upper()
def edit(self, obj):
return "Edit"
このアイデアを自分でフォローした後(リスト表示から実際のページにリンクするため)、私は考え直しました。考慮しなければならない2つのページがあります。モデルの管理ページとモデルの実際の公開ページ(おそらく詳細ビュー)です。管理者から公開ページにリンクすると(CMSページであっても)、管理者ページへの接続が失われます。
モデルの管理ページは、実際には「プレビュー」リンク(通常は右上に配置されています)を介して公開ページにリンクしています。このリンクはmodel_object.get_absolute_url()
から派生しています。
したがって、プレビューリンクが指す場所を変更する場合は、get_absolute_url()
をオーバーライドするだけです。そしてこの場合、とにかくそれを行うのはおそらく良いことです。なぜなら、他のすべての場所でもそのURLを利用したいと思うからです。
リンクはそこでラップされているため、テンプレートをオーバーライドする必要があります。 Edit Django User admin template をご覧ください。