Есть ли способ создать модель только для чтения в администраторе django? но я имею в виду всю модель. Итак, не добавляйте, не удаляете, не меняете, просто видите объекты и поля, все как только для чтения?
ModelAdmin предоставляет hook get_readonly_fields () - следующее непроверено, моя идея состоит в том, чтобы определить все поля, как это делает ModelAdmin, без использования рекурсии с самими полями readonly:
from django.contrib.admin.util import flatten_fieldsets
class ReadOnlyAdmin(ModelAdmin):
def get_readonly_fields(self, request, obj=None):
if self.declared_fieldsets:
fields = flatten_fieldsets(self.declared_fieldsets)
else:
form = self.get_formset(request, obj).form
fields = form.base_fields.keys()
return fields
затем подкласс/mixin этого администратора, если он должен быть администратором только для чтения.
Для добавления/удаления и исчезновения их кнопок вы, вероятно, также захотите добавить
def has_add_permission(self, request):
# Nobody is allowed to add
return False
def has_delete_permission(self, request, obj=None):
# Nobody is allowed to delete
return False
P.S .: В ModelAdmin, если has_change_permission (lookup или ваше переопределение) возвращает False, вы не попадаете в представление изменения объекта - и ссылка на него даже не будет показана. Было бы здорово, если бы это произошло, и по умолчанию get_readonly_fields () проверил разрешение на изменение и в этом случае установил все поля только для чтения, как указано выше. Таким образом, не-чейнджеры могли бы, по крайней мере, просматривать данные ... учитывая, что текущая структура администратора предполагает view = edit, как указывает jathanism, это, вероятно, потребует введения разрешения «view» поверх добавления/изменения/удаления ...
EDIT: относительно установки всех полей только для чтения, а также непроверенных, но выглядящих многообещающими:
readonly_fields = MyModel._meta.get_all_field_names()
EDIT: Вот еще один
if self.declared_fieldsets:
return flatten_fieldsets(self.declared_fieldsets)
else:
return list(set(
[field.name for field in self.opts.local_fields] +
[field.name for field in self.opts.local_many_to_many]
))
Как «разрешения просмотра» не попадет в Django 1.11 , к сожалению , вот решение, которое делает ваш ModelAdmin доступным только для чтения , делая как сохранение изменений модели, так и добавление записей журнала истории моделей no-op .
def false(*args, **kwargs):
"""A simple no-op function to make our changes below readable."""
return False
class MyModelReadOnlyAdmin(admin.ModelAdmin):
list_display = [
# list your admin listview entries here (as usual)
]
readonly_fields = [
# list your read-only fields here (as usual)
]
actions = None
has_add_permission = false
has_delete_permission = false
log_change = false
message_user = false
save_model = false
( ПРИМЕЧАНИЕ: Не ошибайтесь помощник false
no-op с встроенным False
. Если вы не сочувствуете вспомогательной функции вне класс переместит его в класс, назовите его no_op
или что-то еще или переопределите затронутые атрибуты обычным def
s. Меньше DRY, но если вам все равно. ..)
Это будет:
Я не буду:
Обратите внимание, что get_all_field_names
(как указано в принятом ответе) был удален в Django 1.10 .
Протестировано с Django 1.10.5.
Вы можете настроить классы ModelAdmin
с помощью readonly_fields
. Подробнее см. этот ответ .
Согласно моему тесту на Django 1.8, мы не можем использовать следующее, как указано в ответе № 3, но оно работает на Django 1.4 :
## self.get_formset(request, obj) ##
answer 3 needs fix. Generally, alternative codes for this issue about below section
## form = self.get_formset(request, obj).form ##
## fields = form.base_fields.keys() ##
Может быть что-то вроде:
#~ (A) or
[f.name for f in self.model._meta.fields]
#~ (B) or
MyModel._meta.get_all_field_names()
#~ (C)
list(set([field.name for field in self.opts.local_fields] +
[field.name for field in self.opts.local_many_to_many]
))
У меня был аналогичный сценарий, где:
Поскольку в ModelAdmin можно переопределить change_view ()
, мы можем использовать это, чтобы предотвратить редактирование экземпляров модели после их создания. Вот пример, который я использовал:
def change_view(self, request, object_id, form_url='', extra_context=None):
messages.error(request, 'Sorry, but editing is NOT ALLOWED')
return redirect(request.META['HTTP_REFERER'])
Я также понял, что docs интерпретируют результат ModelAdmin.has_change_permission ()
по-разному:
Должен возвращать True, если разрешено редактирование obj, в противном случае False. Если obj - None, должен возвращать True или False, чтобы указать, будет ли редактирование объектов этого типа разрешено вообще (например, False будет интерпретируется как означающее, что текущему пользователю не разрешено редактировать любой объект этого типа).
Значение Я мог проверить, является ли obj
None
, и в этом случае я возвращаю True
, в противном случае я возвращаю False
и это фактически позволяет пользователям просматривать список изменений, но не иметь возможности редактировать или просматривать change_form после сохранения экземпляра модели.
def has_change_permission(self, request, obj = None, **kwargs):
if obj is None:
return True
else:
return False
Хотя я думаю, что это может также переопределить любые разрешения MODEL_can_change
, позволяющие нежелательным глазам просматривать список изменений?