管理インターフェイスでモデルを完全に読み取り専用にするにはどうすればよいですか?これは、管理機能を使用して検索、並べ替え、フィルタリングなどを行う一種のログテーブル用ですが、ログを変更する必要はありません。
これが重複しているように見える場合は、ここにnotがあります:
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):
pass
templates/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
(変更を禁止すると、オブジェクトを見ることさえできなくなります)
すべてのフィールドの読み取り専用設定を自動化しようとする未テストのコードについては、 読み取り専用としてのモデル全体
編集:テストもされていませんが、私のLogEntryAdminを見て、
readonly_fields = MyModel._meta.get_all_field_names()
それがすべての場合に機能するかどうかわからない。
編集:QuerySet.delete()はまだオブジェクトを一括削除できます。これを回避するには、独自の「オブジェクト」マネージャーと、削除しない対応するQuerySetサブクラスを提供します- DjangoでQuerySet.delete()をオーバーライドする を参照してください
モデルを作成するために使用している、またはインライン読み取り専用の2つのクラスを次に示します。
モデル管理者の場合:
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
ユーザーが編集できないことを認識したい場合は、最初のソリューションで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
2つ目:読み取り専用ソリューションはプレーンモデルで正常に機能します。ただし、外部キーを持つ継承モデルがある場合、[〜#〜] not [〜#〜]は機能します。残念ながら、その解決策はまだわかりません。良い試みは次のとおりです。
しかし、それは私にとってもうまくいきません。
最後の注意点として、広範なソリューションを検討する場合は、各インラインも読み取り専用にする必要があります。
実際、次の簡単な解決策を試すことができます。
_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を返すと、そのモデルの新しいオブジェクトの作成が回避されますこれは、18年8月1日にリリースされたDjango 2.1に追加されました!
ModelAdmin.has_view_permission()
は、既存のhas_delete_permission、has_change_permission、およびhas_add_permissionと同じです。あなたはドキュメントでそれを読むことができます here
リリースノートから:
これにより、ユーザーに管理者のモデルへの読み取り専用アクセス権を付与できます。 ModelAdmin.has_view_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 adminがDjango module "Django-admin-view-を利用して終了した特定のユーザーのすべてのフィールドを読み取り専用にする必要がある場合、同じ要件に遭遇しました独自のコードをローリングせずに許可」を選択します。どのフィールドを明示的に定義するために、よりきめ細かい制御が必要な場合は、モジュールを拡張する必要があります。プラグインの動作を確認できます here
pipenv install Django-admin-view-permission
6666
インラインを含むユーザーのアクセス許可に応じて読み取り専用ビューを処理する汎用クラスを作成しました;)
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, ... )