web-dev-qa-db-ja.com

Djangoの管理でオブジェクトを編集するためのリンクを無効にしますか(表示リストのみ)?

Djangoの管理者は、「変更するアイテムの選択」ページにあるリンクをdisableして、ユーザーがどこにもアイテムを編集できないようにします。 (このリストでユーザーが実行できることを、ドロップダウンアクションのセットに制限します-フィールドの実際の編集はありません)。

Djangoには リンクを表示するフィールドを選択 する機能があることがわかりますが、どうすればよいかわかりませんなし

class HitAdmin(admin.ModelAdmin):
    list_display = ('user','ip','user_agent','hitcount')
    search_fields = ('ip','user_agent')
    date_hierarchy = 'created'
    list_display_links = [] # doesn't work, goes to default

編集するリンクなしでオブジェクトリストを取得する方法はありますか?

44
thornomad

リストとしてのみLog Viewerが必要でした。

私はそれをこのように機能させました:

_class LogEntryAdmin(ModelAdmin):
    actions = None
    list_display = (
        'action_time', 'user',
        'content_type', 'object_repr', 
        'change_message')

    search_fields = ['=user__username', ]
    fieldsets = [
        (None, {'fields':()}), 
        ]

    def __init__(self, *args, **kwargs):
        super(LogEntryAdmin, self).__init__(*args, **kwargs)
        self.list_display_links = (None, )
_

それは、両方の答えの混合のようなものです。

self.list_display_links = ()だけを実行すると、リンクが表示されます。とにかく、_template-tag_コード(templatetags/admin_list.py)が再度チェックして、リストが空かどうかを確認します。

61
Federico

これを適切に行うには、2つのステップが必要です。

  • 編集リンクを非表示にして、誤って詳細ページ(ビューの変更)につまずくことがないようにします。
  • 変更ビューを変更して、リストビューにリダイレクトします。

2番目の部分は重要です。これを行わない場合でも、URLを直接入力することで、人々は引き続き変更ビューにアクセスできます(おそらく望まないでしょう)。これは、OWASPが "Insecure Direct Object Reference" と呼んでいるものと密接に関連しています。

この回答の一部として、示されているすべての機能を提供するために使用できるReadOnlyMixinクラスを作成します。

編集リンクを非表示にする

Django 1.7はこれを本当に簡単にします:list_display_linksNoneに設定するだけです。

class ReadOnlyMixin(): # Add inheritance from "object" if using Python 2
    list_display_links = None

Django 1.6(おそらく以前のバージョン)では、これはそれほど単純なことではありません。この質問に対するかなり多くの回答が、オブジェクトの構築後に__init__を設定するためにlist_display_linksをオーバーライドすることを提案していますが、これにより再利用が難しくなります(コンストラクターを一度しかオーバーライドできません)。

私は、Djangoのget_list_display_linksメソッドを次のようにオーバーライドすることをお勧めします。

def get_list_display_links(self, request, list_display):
    """
    Return a sequence containing the fields to be displayed as links
    on the changelist. The list_display parameter is the list of fields
    returned by get_list_display().

    We override Django's default implementation to specify no links unless
    these are explicitly set.
    """
    if self.list_display_links or not list_display:
        return self.list_display_links
    else:
        return (None,)

これにより、ミックスインが使いやすくなります。デフォルトでは編集リンクが非表示になりますが、特定の管理ビューで必要な場合は、リンクを元に戻すことができます。

リストビューへのリダイレクト

change_viewメソッドをオーバーライドして、詳細ページの動作(ビューの変更)を変更できます。正しいページを自動的に見つけるChris Prattによって提案された手法の拡張は次のとおりです。

enable_change_view = False

def change_view(self, request, object_id, form_url='', extra_context=None):
    """
    The 'change' admin view for this model.

    We override this to redirect back to the changelist unless the view is
    specifically enabled by the "enable_change_view" property.
    """
    if self.enable_change_view:
        return super(ReportMixin, self).change_view(
            request,
            object_id,
            form_url,
            extra_context
        )
    else:
        from Django.core.urlresolvers import reverse
        from Django.http import HttpResponseRedirect

        opts = self.model._meta
        url = reverse('admin:{app}_{model}_changelist'.format(
            app=opts.app_label,
            model=opts.model_name,
        ))
        return HttpResponseRedirect(url)

これもカスタマイズ可能です。enable_change_viewTrueに切り替えることで、詳細ページをオンに戻すことができます。

「追加[〜#〜]アイテム[〜#〜]」ボタンを削除する

最後に、ユーザーが新しいアイテムを追加または削除しないようにするために、次のメソッドをオーバーライドすることができます。

def has_add_permission(self, request):
    return False

def has_delete_permission(self, request, obj=None):
    return False

これらの変更により:

  • 「追加アイテム」ボタンを無効にする
  • uRLに/addを追加して、ユーザーがアイテムを直接追加できないようにします
  • 一括削除を防ぐ

最後に、actionsパラメータを変更して、「選択した項目を削除items」アクションを削除できます。

すべてを一緒に入れて

これが完成したミックスインです:

from Django.core.urlresolvers import reverse
from Django.http import HttpResponseRedirect

class ReadOnlyMixin(): # Add inheritance from "object" if using Python 2

    actions = None

    enable_change_view = False

    def get_list_display_links(self, request, list_display):
        """
        Return a sequence containing the fields to be displayed as links
        on the changelist. The list_display parameter is the list of fields
        returned by get_list_display().

        We override Django's default implementation to specify no links unless
        these are explicitly set.
        """
        if self.list_display_links or not list_display:
            return self.list_display_links
        else:
            return (None,)

    def change_view(self, request, object_id, form_url='', extra_context=None):
        """
        The 'change' admin view for this model.

        We override this to redirect back to the changelist unless the view is
        specifically enabled by the "enable_change_view" property.
        """
        if self.enable_change_view:
            return super(ReportMixin, self).change_view(
                request,
                object_id,
                form_url,
                extra_context
            )
        else:
            opts = self.model._meta
            url = reverse('admin:{app}_{model}_changelist'.format(
                app=opts.app_label,
                model=opts.model_name,
            ))
            return HttpResponseRedirect(url)

    def has_add_permission(self, request):
        return False

    def has_delete_permission(self, request, obj=None):
        return False
33
simpleigh

Django 1.7以降では、

class HitAdmin(admin.ModelAdmin):
    list_display_links = None
18
Blaise

ユーザーomatは、上のコメントで述べたように、単にリンクを削除しようとしても、ユーザーが変更ページに手動でアクセスするのを妨げることはありません。ただし、これも簡単に修正できます。

class MyModelAdmin(admin.ModelAdmin)
    # Other stuff here
    def change_view(self, request, obj=None):
        from Django.core.urlresolvers import reverse
        from Django.http import HttpResponseRedirect
        return HttpResponseRedirect(reverse('admin:myapp_mymodel_changelist'))
18
Chris Pratt

モデル管理セットで:

list_display_links = (None,)

それでうまくいくはずです。 (とにかく1.1.1で動作します。)

ドキュメントへのリンク: list_display_links

7
Josh Ourisman

注意事項として、changelist_viewを変更できます。

class SomeAdmin(admin.ModelAdmin):
    def changelist_view(self, request, extra_context=None):
        self.list_display_links = (None, )
        return super(SomeAdmin, self).changelist_view(request, extra_context=None)

これは私にとってはうまくいきます。

2
tinti

これを行うためのサポートされている方法はありません。

コードを見ると、何も設定しなければ、自動的にModelAdmin.list_display_linksが最初の要素に設定されるようです。したがって、最も簡単な方法は、ModelAdminサブクラスの__init__メソッドをオーバーライドして、初期化時にその属性の設定を解除することです。

class HitAdmin(admin.ModelAdmin):
    list_display = ('user','ip','user_agent','hitcount')
    search_fields = ('ip','user_agent')
    date_hierarchy = 'created'

    def __init__(self, *args, **kwargs):
        super(HitAdmin, self).__init__(*args, **kwargs)
        self.list_display_links = []

非常に大ざっぱなテストの後、これはうまくいくようです。ただし、他の場所で問題が発生しないことや、Djangoの将来の変更によって問題が発生しないことは保証できません。

コメントの後に編集

ソースにパッチを当てる必要はありません、これはうまくいくでしょう:

    def __init__(self, *args, **kwargs):
        if self.list_display_links:
            unset_list_display = True
        else:
            unset_list_display = False
        super(HitAdmin, self).__init__(*args, **kwargs)
        if unset_list_display:
            self.list_display_links = []

しかし、Djangoにパッチが受け入れられるかどうかは非常に疑わしいものです。これは、現時点でコードが明示的に行っていることを壊してしまうためです。

2
Daniel Roseman

書くだけ list_display_links = None管理者

2
Sameer Yadav

Django 1.6.2を使用すると、次のようになります。

class MyAdmin(admin.ModelAdmin):

    def get_list_display_links(self, request, list_display):
        return []

自動生成されたリンクはすべて非表示になります。

1
truease.com

Djangoのより「最近の」バージョンでは、少なくとも1.9以降、管理クラスの追加、変更、削除の権限を簡単に決定できます。 Django管理ドキュメント を参照してください。次に例を示します。

@admin.register(Object)
class Admin(admin.ModelAdmin):

    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False
1
shezi

ridiculouslyハックすることもできます(_init_のオーバーライドで大騒ぎしたくない場合)そして、基本的に次のような最初の要素の値を提供します。

_</a>My non-linked value<a>
_

私は知っています、あまりきれいではありませんが、マークアップを変更するだけなので、他の場所で何かを壊す心配は少ないでしょう。

これがどのように機能するかについてのサンプルコードは次のとおりです:

_class HitAdmin(admin.ModelAdmin):
    list_display = ('user_no_link','ip','user_agent','hitcount')

    def user_no_link(self, obj):
        return u'</a>%s<a>' % obj
    user_no_link.allow_tags = True
    user_no_link.short_description = "user"
_

補足:return u'%s' % obj.get_full_name()を返すことで、出力を読みやすくすることもできます(リンクにしたくないため)。

1
T. Stone

Get list_display_linksメソッドとアクションをNoneにオーバーライドします。

class ChangeLogAdmin(admin.ModelAdmin):
    actions = None
    list_display = ('asset', 'field', 'before_value', 'after_value', 'operator', 'made_at')

    fieldsets = [
        (None, {'fields': ()}),
    ]

    def __init__(self, model, admin_site):
        super().__init__(model, admin_site)

    def get_list_display_links(self, request, list_display):
        super().get_list_display_links(request, list_display)
        return None
0
Jake Jeon