Модели только для чтения в интерфейсе администратора Django?
Как я могу сделать модель полностью только для чтения в интерфейсе администратора? Это для своего рода таблицы журнала, где я использую функции администратора для поиска, сортировки, фильтрации и т. д., Но нет необходимости изменять журнал.
в случае, если это выглядит как дубликат, вот не что я пытаюсь сделать:
- Я не ищу только для чтения поля (даже создание каждого поля только для чтения все равно позволит вам создавать новые записи)
- Я не глядя на создание только для чтения пользователей: каждый пользователь должен быть readonly.
12 ответов:
см.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 actions["delete_selected"] 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): passtemplates / 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 %}
администратор предназначен для редактирования, а не только для просмотра (вы не найдете разрешение "просмотр"). Для того, чтобы достичь того, чего вы хотите, вам придется запретить добавление, удаление, и сделать все поля только для чтения:
class MyAdmin(ModelAdmin): def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False(Если вы запретите изменение вы даже не получите, чтобы увидеть объекты)
для некоторого непроверенного кода, который пытается автоматизировать настройку всех полей только для чтения, см. Мой ответ на вся модель как только для чтения
EDIT: также непроверенный, но просто взглянул на мой Логентрядмин и есть
readonly_fields = MyModel._meta.get_all_field_names()Не знаю, будет ли это работать во всех случаях.
EDIT: QuerySet.delete () по-прежнему может выполнять массовое удаление объектов. Чтобы обойти это, предоставьте свой собственный менеджер "объектов" и соответствующий подкласс QuerySet, который не удаляет - см. Переопределение QuerySet.удалить() в Django
вот два класса, которые я использую, чтобы сделать модель и/или это строки только для чтения.
для модели admin:
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для inlines:
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
Если вы хотите, чтобы пользователь узнал, что он / она не может редактировать его, 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 позволяет избежать создания новых объектов для этой модели
если принятый ответ не работает для вас, попробуйте это:
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 's отличные ответы, плюс добавление немного больше, чтобы удалить кнопки" Сохранить "и" сохранить и продолжить " приводит к (в синтаксисе 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 admin, в конечном итоге использовал модуль django "django-admin-view-permission" без прокатки моего собственного кода. Если вам нужен более мелкозернистый контроль, чтобы явно определить, какие поля, то вам нужно будет расширить модуль. Вы можете проверить плагин в действии здесь
Это было добавлено в Django 2.1, который был выпущен на 8/1/18!
ModelAdmin.has_view_permission()Так же, как существующие has_delete_permission, has_change_permission и has_add_permission. Вы можете прочитать об этом в документации здесьв выпуске:
Это позволяет предоставлять пользователям доступ только для чтения к моделям в admin. ModelAdmin.has_view_permission () является новым. Реализация обратная совместимость в том, что нет необходимости чтобы назначить "вид" разрешение разрешить пользователям, имеющим разрешение" изменить", редактировать объекты.
только для чтения => разрешение мнения
pipenv install django-admin-view-permission- добавить 'admin_view_permission' для INSTALLED_APPS в settings.py. like это: 'INSTALLED_APPS = [ 'admin_view_permission',
- python manage.py мигрировать
- python manage.py runserver
6666ОК.удачи с разрешением "просмотры"
Я написал универсальный класс для обработки представления только для чтения в зависимости от разрешений пользователя, включая строки;)
In 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 TrueIn 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, ... )
Comments