python - template - 在django的admin(僅顯示列表)中禁用編輯對象的鏈接?




django admin template github (7)

在Django的管理員中,我想禁用 “選擇要更改的項目”頁面上提供的鏈接,這樣用戶就無法去任何地方編輯項目。 (我將限制用戶可以對此列表執行的操作到一組下拉操作 - 沒有實際編輯字段)。

我看到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

任何想法如何獲取我的對象列表沒有任何鏈接編輯?


作為上述評論中提到的用戶,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'))

你也可能是荒謬的 hacky(如果你不想對重寫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()來提高輸出的可讀性(因為您不希望它成為鏈接),這可能是有點整潔,具體取決於您的用例。


只需在管理員中寫入list_display_links = None


在Django 1.7及更高版本中,你可以做到

class HitAdmin(admin.ModelAdmin):
    list_display_links = None

我只想將日誌查看器作為列表。

我得到它像這樣工作:

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)再次檢查以查看列表是否為空。


正確執行此操作需要兩個步驟:

  • 隱藏編輯鏈接,因此沒有人在錯誤的詳細信息頁面(更改視圖)上絆倒。
  • 修改更改視圖以重定向回列表視圖。

第二部分很重要:如果你不這樣做,那麼人們仍然可以通過直接輸入URL來訪問更改視圖(這可能是你不想要的)。 這與OWASP所稱的“不安全直接對象參考”密切相關。

作為這個答案的一部分,我將構建一個ReadOnlyMixin類,可用於提供所有顯示的功能。

隱藏編輯鏈接

Django 1.7非常簡單:只需將list_display_links設置為None

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

這使得我們的mixin易於使用:它默認隱藏編輯鏈接,但允許我們在特定管理視圖需要時將其添加回來。

重定向到列表視圖

我們可以通過覆蓋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_view切換為True您可以重新打開詳細信息頁面。

刪除“添加項目 ”按鈕

最後,您可能希望覆蓋以下方法,以防止人們添加或刪除新項目。

def has_add_permission(self, request):
    return False

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

這些變化將:

  • 禁用“添加項目 ”按鈕
  • 通過附加/add到URL來阻止人們直接添加項目
  • 防止批量刪除

最後,您可以通過修改actions參數來刪除“刪除所選項目 ”操作。

把它們放在一起

這是完成的mixin:

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

與django 1.6.2你可以這樣做:

class MyAdmin(admin.ModelAdmin):

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

它將隱藏所有自動生成的鏈接。





modeladmin