web-dev-qa-db-ja.com

Django管理者リスト表示の外部キー

Djangoモデルに外部キーフィールドが含まれていて、そのフィールドがリストモードで表示されている場合、text、外部オブジェクトへのlinkを表示する代わりに。

すべての外部キーをフラットテキストではなくリンクとして自動的に表示することは可能ですか?

(もちろん、フィールドごとに行うことも可能ですが、一般的な方法はありますか?)

class Author(models.Model):
    ...

class Post(models.Model):
    author = models.ForeignKey(Author)

次に、作成者がリストモードで表示されるようにModelAdminを選択します。

class PostAdmin(admin.ModelAdmin):
    list_display = [..., 'author',...]

リストモードでは、作成者フィールドはAuthorクラスの__unicode__メソッドを使用して作成者を表示します。その上に、管理サイトの対応する著者のURLを指すlinkが欲しいです。それは可能ですか?

手動による方法

完全を期すために、手動の方法を追加します。 PostAdminクラスにメソッドauthor_linkを追加します。

def author_link(self, item):
    return '<a href="../some/path/%d">%s</a>' % (item.id, unicode(item))
author_link.allow_tags = True

それはその特定のフィールドで機能しますが、それはnotです。同じ効果を得るには、一般的な方法が必要です。 (問題の1つは、Django管理サイトのオブジェクトへのパスを自動的に把握する方法です。)

37
Olivier Verdier

箱から出して自動的にやりたいことをするメカニズムはないと思います。

しかし、オブジェクトのIDに基づいて管理編集ページへのパスを決定する限り、必要なのは2つの情報だけです。

a)self.model._meta.app_label

b)self.model._meta.module_name

次に、たとえば、そのモデルの編集ページに移動するには、次のようにします。

'../%s_%s_change/%d' % (self.model._meta.app_label, self.model._meta.module_name, item.id)

を見てみましょう Django.contrib.admin.options.ModelAdmin.get_urlsをご覧ください。

モデル名とIDを受け取り、ラベルと名前を取得するためだけに指定されたタイプのモデルを作成し(データベースにアクセスする必要はありません)、上記のURL aを生成するcallableがあると思います。

しかし、インラインを使用して取得できないと確信していますか?関連するすべてのコンポーネントを1つのページに表示すると、ユーザーインターフェースが改善されます...

編集:

Inlines (ドキュメントにリンク)により、管理者インターフェイスは親子関係を2つに分割する代わりに1つのページに表示できます。

提供した投稿/著者の例では、インラインを使用すると、投稿を編集するためのページに、著者を追加/編集/削除するためのインラインフォームも表示されます。エンドユーザーにとってははるかに自然です。

管理者リストビューで実行できることは、投稿者のコンマ区切りリストをレンダリングするPostモデルで呼び出し可能なオブジェクトを作成することです。そのため、適切な著者を示す投稿リストビューが表示され、投稿に関連付けられた著者を投稿管理インターフェースで直接編集します。

9
cethegeek

私は同じ問題の解決策を探していて、この質問に出くわしました...自分で解決することになりました。 OPはもう興味がないかもしれませんが、これはまだ誰かにとって役立つかもしれません。

from functools import partial
from Django.forms import MediaDefiningClass

class ModelAdminWithForeignKeyLinksMetaclass(MediaDefiningClass):

    def __getattr__(cls, name):

        def foreign_key_link(instance, field):
            target = getattr(instance, field)
            return u'<a href="../../%s/%s/%d">%s</a>' % (
                target._meta.app_label, target._meta.module_name, target.id, unicode(target))

        if name[:8] == 'link_to_':
            method = partial(foreign_key_link, field=name[8:])
            method.__name__ = name[8:]
            method.allow_tags = True
            setattr(cls, name, method)
            return getattr(cls, name)
        raise AttributeError

class Book(models.Model):
    title = models.CharField()
    author = models.ForeignKey(Author)

class BookAdmin(admin.ModelAdmin):
    __metaclass__ = ModelAdminWithForeignKeyLinksMetaclass

    list_display = ('title', 'link_to_author')

python> = 2.5を使用しない場合は、 'partial'をDjangoの 'curry'に置き換えます。

18
Itai Tavor

https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#admin-reverse-urls を参照してください

例:

from Django.utils.html import format_html
def get_admin_change_link(app_label, model_name, obj_id, name):
    url = reverse('admin:%s_%s_change' % (app_label, model_name),
              args=(obj_id,))
    return format_html('<a href="%s">%s</a>' % (
        url, unicode(name)
    ))
4
adolgarev