Отключить ссылку для редактирования объекта в Администраторе django (только список отображения)?
в администратора Django, я хочу!--2-->отключить ссылки, предоставленные на странице "выбор элемента для изменения", чтобы пользователи не могли никуда перейти для редактирования элемента. (Я собираюсь ограничить то, что пользователи могут делать с этим списком, набором выпадающих действий - без фактического редактирования полей).
Я вижу, что 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
любой идеи как получить список объектов без каких-либо ссылок для редактирования?
9 ответов
Я хотел, чтобы просмотрщик журналов был только списком.
Я заставил его работать так:
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
класс, который можно использовать для предоставления всех показанных функций.
скрытие ссылки редактирования
Джанго 1.7 делает это очень легко: вы просто list_display_links
to 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
метод. Вот расширение к методу, предложенному Крисом Праттом, который автоматически находит нужную страницу:
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
to True
вы можете снова включить страницу сведений.
удаление "Add элемент"
наконец, вы можете переопределить следующие методы, чтобы предотвратить добавление или удаление новых предметы.
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
эти изменения будут:
- отключить "добавить элемент"
- запретить людям напрямую добавлять элементы, добавляя
/add
к URL - предотвратить массовое удаление
наконец, вы можете удалить "Удалить выбранные предметы" действие путем изменения
как пользователь, 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'))
в Django 1.7 и более поздних версиях вы можете сделать
class HitAdmin(admin.ModelAdmin):
list_display_links = None
в вашей модели admin set:
list_display_links = (None,)
Это должно сделать это. (Работает в 1.1.1 в любом случае.)
ссылка на документы: list_display_links
нет поддерживаемого способа сделать это.
глядя на код, кажется, что он автоматически устанавливает ModelAdmin.list_display_links
к первому элементу, если вы ничего не установите. Таким образом, самый простой способ может быть переопределить __init__
метод ModelAdmin
подкласс для снятия этого атрибута при инициализации:
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 = []
это, кажется, работает, после очень беглого теста. Я не могу гарантировать, что это не сломает ничего в другом месте, или что это не будет сломано будущими изменениями Хотя Джанго.
редактировать после комментария:
нет необходимости исправлять источник, это будет работать:
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, так как это нарушает то, что код явно делает в данный момент.
только для заметок вы можете изменить 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)
это отлично работает для меня.
вы также может быть смешно 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()
что может быть очень аккуратным в зависимости от вашего варианта использования.
с django 1.6.2 вы можете сделать так:
class MyAdmin(admin.ModelAdmin):
def get_list_display_links(self, request, list_display):
return []
он скроет все автоматически сгенерированные ссылки.