Django 관리 인터페이스의 읽기 전용 모델?
관리자 인터페이스에서 모델을 완전히 읽기 전용으로 만들려면 어떻게해야합니까? 관리 기능을 사용하여 검색, 정렬, 필터링 등을하는 일종의 로그 테이블 용이지만 로그를 수정할 필요가 없습니다.
경우이 모습은 여기, 중복을 좋아 하지 내가 할 노력하고있어 :
- 읽기 전용 필드를 찾고 있지 않습니다 (모든 필드를 읽기 전용으로 설정해도 새 레코드를 만들 수 있음).
- 읽기 전용 사용자 를 만들려는 것이 아닙니다 . 모든 사용자는 읽기 전용이어야합니다.
참조 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
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 () 재정의를 참조하십시오.
다음은 모델을 만드는 데 사용하는 두 가지 클래스 및 / 또는 인라인 읽기 전용입니다.
모델 관리자 :
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
사용자가 편집 할 수 없다는 사실을 알리려면 첫 번째 솔루션에서 두 가지가 누락되었습니다. 삭제 작업을 제거했습니다!
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를 반환하면 해당 모델에 대한 새 개체가 생성되지 않습니다.
이것은 8/1/18에 출시 된 Django 2.1에 추가되었습니다!
ModelAdmin.has_view_permission()
기존 has_delete_permission, has_change_permission 및 has_add_permission과 같습니다. 여기 문서에서 읽을 수 있습니다.
릴리스 정보에서 :
이를 통해 사용자에게 관리자의 모델에 대한 읽기 전용 액세스 권한을 부여 할 수 있습니다. 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에서만 이것을 시도했습니다.
The accepted answer should work, but this will also preserve the display order of the readonly fields. You also don't have to hardcode the model with this solution.
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
I ran into the same requirement when needing to make all fields readonly for certain users in django admin ended up leveraging on django module "django-admin-view-permission" without rolling my own code. If you need more fine grained control to explicitly define which fields then you would need to extend the module. You can check out the plugin in action here
read-only => views permission
pipenv install django-admin-view-permission
- add 'admin_view_permission' to INSTALLED_APPS in the settings.py.like this: `INSTALLED_APPS = [ 'admin_view_permission',
- python manage.py migrate
- python manage.py runserver
6666
ok.have fun with the 'views' permission
I have written a generic class to handle ReadOnly view depending on User permissions, including inlines ;)
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 True
In 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 )
Then, we can just inherit normally our classes in admin.py:
class ContactAdmin(ReadOnlyAdmin):
list_display = ("name","email","whatever")
readonly_fields = ("updated","created")
inlines = ( PhoneInline, ... )
참고URL : https://stackoverflow.com/questions/8265328/readonly-models-in-django-admin-interface
'Nice programing' 카테고리의 다른 글
.NET Framework에서 람다와 대리자의 차이점은 무엇입니까? (0) | 2020.10.18 |
---|---|
Vim yanking 라인 범위 (0) | 2020.10.18 |
비취 / 퍼그 댓글 (0) | 2020.10.18 |
DLL에서 동적으로 함수로드 (0) | 2020.10.18 |
Spring Boot : favicon 재정의 (0) | 2020.10.18 |