Как сделать модель полностью доступной только для чтения в интерфейсе администратора? Это своего рода таблица журнала, где я использую функции администратора для поиска, сортировки, фильтрации и т. Д., Но нет необходимости изменять журнал.
В случае , если это выглядит как дубликат, вот не то , что я пытаюсь сделать:
- Я не ищу поля только для чтения (даже если сделать каждое поле только для чтения, вы все равно сможете создавать новые записи)
- Я не собираюсь создавать пользователя только для чтения : каждый пользователь должен быть доступен только для чтения.
django
django-admin
readonly
Стив Беннетт
источник
источник
has_view_permission
был наконец реализован в Django 2.1. Также см. Stackoverflow.com/a/51641149 ниже.Ответы:
См. Https://djangosnippets.org/snippets/10539/
class ReadOnlyAdminMixin(object): """Disables all editing capabilities.""" change_form_template = "admin/view.html" def __init__(self, *args, **kwargs): super(ReadOnlyAdminMixin, self).__init__(*args, **kwargs) self.readonly_fields = self.model._meta.get_all_field_names() def get_actions(self, request): actions = super(ReadOnlyAdminMixin, self).get_actions(request) del_action = "delete_selected" if del_action in actions: del actions[del_action] return actions def has_add_permission(self, request): return False def has_delete_permission(self, request, obj=None): return False def save_model(self, request, obj, form, change): pass def delete_model(self, request, obj): pass def save_related(self, request, form, formsets, change): pass
шаблоны / admin / view.html
{% extends "admin/change_form.html" %} {% load i18n %} {% block submit_buttons_bottom %} <div class="submit-row"> <a href="../">{% blocktrans %}Back to list{% endblocktrans %}</a> </div> {% endblock %}
templates / admin / view.html (для Grappelli)
{% extends "admin/change_form.html" %} {% load i18n %} {% block submit_buttons_bottom %} <footer class="grp-module grp-submit-row grp-fixed-footer"> <header style="display:none"><h1>{% trans "submit options"|capfirst context "heading" %}</h1></header> <ul> <li><a href="../" class="grp-button grp-default">{% blocktrans %}Back to list{% endblocktrans %}</a></li> </ul> </footer> {% endblock %}
источник
Model
или дляModelAdmin
?ModelAdmin
.Администратор предназначен для редактирования, а не только для просмотра (вы не найдете разрешения «просмотр»). Чтобы добиться желаемого, вам нужно запретить добавление, удаление и сделать все поля доступными только для чтения:
class MyAdmin(ModelAdmin): def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False
(если вы запретите менять, вы даже не увидите объекты)
Для некоторого непроверенного кода, который пытается автоматизировать настройку всех полей только для чтения, см. Мой ответ Целая модель как доступная только для чтения
РЕДАКТИРОВАТЬ: тоже непроверено, но только что взглянул на мой LogEntryAdmin, и у него есть
readonly_fields = MyModel._meta.get_all_field_names()
Не знаю, сработает ли это во всех случаях.
РЕДАКТИРОВАТЬ: QuerySet.delete () все еще может массово удалять объекты. Чтобы обойти это, предоставьте свой собственный менеджер «объектов» и соответствующий подкласс QuerySet, который не удаляется - см. Переопределение QuerySet.delete () в Django.
источник
Вот два класса, которые я использую, чтобы сделать модель и / или встроенную модель только для чтения.
Для администратора модели:
from django.contrib import admin class ReadOnlyAdmin(admin.ModelAdmin): readonly_fields = [] def get_readonly_fields(self, request, obj=None): return list(self.readonly_fields) + \ [field.name for field in obj._meta.fields] + \ [field.name for field in obj._meta.many_to_many] def has_add_permission(self, request): return False def has_delete_permission(self, request, obj=None): return False class MyModelAdmin(ReadOnlyAdmin): pass
Для встроенных:
class ReadOnlyTabularInline(admin.TabularInline): extra = 0 can_delete = False editable_fields = [] readonly_fields = [] exclude = [] def get_readonly_fields(self, request, obj=None): return list(self.readonly_fields) + \ [field.name for field in self.model._meta.fields if field.name not in self.editable_fields and field.name not in self.exclude] def has_add_permission(self, request): return False class MyInline(ReadOnlyTabularInline): pass
источник
has_add_permission
inReadOnlyAdmin
принимает в качестве параметра только запросЕсли вы хотите, чтобы пользователь осознал, что он / она не может его редактировать, в первом решении отсутствуют 2 части. Вы удалили действие удаления!
class MyAdmin(ModelAdmin) def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False def get_actions(self, request): actions = super(MyAdmin, self).get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions
Во-вторых: решение только для чтения отлично работает на простых моделях. Но это НЕ работает, если у вас есть унаследованная модель с внешними ключами. К сожалению, я пока не знаю решения этой проблемы. Хорошая попытка:
Вся модель доступна только для чтения
Но и у меня тоже не работает.
И последнее замечание: если вы хотите обдумать широкое решение, вы должны обеспечить, чтобы каждая строка также была доступна только для чтения.
источник
На самом деле вы можете попробовать это простое решение:
class ReadOnlyModelAdmin(admin.ModelAdmin): actions = None list_display_links = None # more stuff here def has_add_permission(self, request): return False
actions = None
: избегает отображения раскрывающегося списка с опцией «Удалить выбранное ...»list_display_links = None
: избегает нажатия в столбцах для редактирования этого объектаhas_add_permission()
возврат False позволяет избежать создания новых объектов для этой моделиисточник
Это было добавлено в Django 2.1, выпущенный 01.08.18!
ModelAdmin.has_view_permission()
аналогичен существующим has_delete_permission, has_change_permission и has_add_permission. Вы можете прочитать об этом в документации здесьИз примечаний к выпуску:
источник
Если принятый ответ вам не подходит, попробуйте следующее:
def get_readonly_fields(self, request, obj=None): readonly_fields = [] for field in self.model._meta.fields: readonly_fields.append(field.name) return readonly_fields
источник
Компиляция отличных ответов @darklow и @josir плюс добавление еще немного для удаления кнопок «Сохранить» и «Сохранить и продолжить» приводит к (в синтаксисе Python 3):
class ReadOnlyAdmin(admin.ModelAdmin): """Provides a read-only view of a model in Django admin.""" readonly_fields = [] def change_view(self, request, object_id, extra_context=None): """ customize add/edit form to remove save / save and continue """ extra_context = extra_context or {} extra_context['show_save_and_continue'] = False extra_context['show_save'] = False return super().change_view(request, object_id, extra_context=extra_context) def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions def get_readonly_fields(self, request, obj=None): return list(self.readonly_fields) + \ [field.name for field in obj._meta.fields] + \ [field.name for field in obj._meta.many_to_many] def has_add_permission(self, request): return False def has_delete_permission(self, request, obj=None): return False
а затем вы используете как
class MyModelAdmin(ReadOnlyAdmin): pass
Я пробовал это только с Django 1.11 / Python 3.
источник
Принятый ответ должен работать, но это также сохранит порядок отображения полей только для чтения. Вам также не нужно жестко кодировать модель с помощью этого решения.
class ReadonlyAdmin(admin.ModelAdmin): def __init__(self, model, admin_site): super(ReadonlyAdmin, self).__init__(model, admin_site) self.readonly_fields = [field.name for field in filter(lambda f: not f.auto_created, model._meta.fields)] def has_delete_permission(self, request, obj=None): return False def has_add_permission(self, request, obj=None): return False
источник
В Django 2.2 я делаю это так:
@admin.register(MyModel) class MyAdmin(admin.ModelAdmin): readonly_fields = ('all', 'the', 'necessary', 'fields') actions = None # Removes the default delete action in list view 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
источник
readonly_fields
иactions
линия не нужнос django 2.2 администратор только для чтения может быть таким простым, как:
class ReadOnlyAdminMixin(): 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 class LogEntryAdmin(ReadOnlyAdminMixin, admin.ModelAdmin): list_display = ('id', 'user', 'action_flag', 'content_type', 'object_repr')
источник
Я столкнулся с тем же требованием, когда мне нужно было сделать все поля доступными только для чтения для определенных пользователей в django admin в конечном итоге использовать модуль django «django-admin-view-permission» без прокрутки моего собственного кода. Если вам нужен более мелкозернистый элемент управления, чтобы явно определить, какие поля, вам нужно будет расширить модуль. Вы можете проверить работу плагина здесь
источник
только для чтения => разрешение на просмотр
pipenv install django-admin-view-permission
6666
хорошо. развлекайся с разрешением на просмотр
источник
Я написал общий класс для обработки представления ReadOnly в зависимости от разрешений пользователя, включая встроенные;)
В models.py:
class User(AbstractUser): ... def is_readonly(self): if self.is_superuser: return False # make readonly all users not in "admins" group adminGroup = Group.objects.filter(name="admins") if adminGroup in self.groups.all(): return False return True
В admin.py:
# read-only user filter class for ModelAdmin class ReadOnlyAdmin(admin.ModelAdmin): def __init__(self, *args, **kwargs): # keep initial readonly_fields defined in subclass self._init_readonly_fields = self.readonly_fields # keep also inline readonly_fields for inline in self.inlines: inline._init_readonly_fields = inline.readonly_fields super().__init__(*args,**kwargs) # customize change_view to disable edition to readonly_users def change_view( self, request, object_id, form_url='', extra_context=None ): context = extra_context or {} # find whether it is readonly or not if request.user.is_readonly(): # put all fields in readonly_field list self.readonly_fields = [ field.name for field in self.model._meta.get_fields() if not field.auto_created ] # readonly mode fer all inlines for inline in self.inlines: inline.readonly_fields = [field.name for field in inline.model._meta.get_fields() if not field.auto_created] # remove edition buttons self.save_on_top = False context['show_save'] = False context['show_save_and_continue'] = False else: # if not readonly user, reset initial readonly_fields self.readonly_fields = self._init_readonly_fields # same for inlines for inline in self.inlines: inline.readonly_fields = self._init_readonly_fields return super().change_view( request, object_id, form_url, context ) def save_model(self, request, obj, form, change): # disable saving model for readonly users # just in case we have a malicious user... if request.user.is_readonly(): # si és usuari readonly no guardem canvis return False # if not readonly user, save model return super().save_model( request, obj, form, change )
Затем мы можем просто наследовать наши классы в admin.py:
class ContactAdmin(ReadOnlyAdmin): list_display = ("name","email","whatever") readonly_fields = ("updated","created") inlines = ( PhoneInline, ... )
источник