Readonly modele w interfejsie admina Django?
Jak Zrobić model Całkowicie tylko do odczytu w interfejsie administratora? Jest to rodzaj tabeli dziennika, gdzie używam funkcji administratora do wyszukiwania, sortowania, filtrowania itp., ale nie ma potrzeby modyfikowania dziennika.
W przypadku, gdy wygląda to jak duplikat, oto NIE co próbuję zrobić:
- nie szukam pól readonly (nawet zrobienie każdego pola readonly pozwoli na tworzenie nowych rekordów)
- nie chcę tworzyć readonly user : każdy użytkownik powinien być tylko readonly.
12 answers
Zobacz 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 (dla 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 %}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-05 11:50:12
Administrator służy do edycji, a nie tylko do przeglądania (nie znajdziesz uprawnień "widoku"). Aby osiągnąć to, co chcesz, musisz zabronić dodawania, usuwania i uczynić wszystkie pola readonly:
class MyAdmin(ModelAdmin):
def has_add_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return False
(jeśli zabronisz zmiany, nie zobaczysz nawet obiektów)
Dla jakiegoś nieprzetestowanego kodu, który próbuje zautomatyzować ustawianie wszystkich pól tylko do odczytu zobacz moją odpowiedź na cały model jako Tylko do odczytu
EDIT: również niesprawdzony, ale po prostu spojrzałem na mój LogEntryAdmin i to has
readonly_fields = MyModel._meta.get_all_field_names()
Nie wiem, czy to zadziała we wszystkich przypadkach.
EDIT: QuerySet.delete () może nadal masowo usuwać obiekty. Aby to obejść, podaj swój własny menedżer "obiektów" i odpowiadającą mu podklasę QuerySet, która nie jest usuwana - zobacz nadpisywanie QuerySet.delete () in Django
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:16
Oto dwie klasy, których używam do tworzenia modelu i / lub jest tylko do odczytu w liniach.
Dla modela admina:
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
Dla linii:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-03 11:45:37
Jeśli chcesz, aby użytkownik wiedział, że nie może go edytować, brakuje 2 elementów na pierwszym rozwiązaniu. Musisz usunąć akcję Usuń!
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
Po drugie: rozwiązanie readonly działa dobrze na zwykłych modelach. Ale to działa NIE Jeśli masz odziedziczony model z kluczami obcymi. Niestety, nie znam jeszcze rozwiązania. Dobra próba to:
Cały model jako Tylko do odczytu
Ale dla mnie to też nie działa.I finał uwaga, jeśli chcesz myśleć o szerokim rozwiązaniu, musisz wymusić, że każda linia inline musi być również readonly.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:16
W rzeczywistości można spróbować tego prostego rozwiązania:
class ReadOnlyModelAdmin(admin.ModelAdmin):
actions = None
list_display_links = None
# more stuff here
def has_add_permission(self, request):
return False
-
actions = None
: unika wyświetlania rozwijanej listy z "Usuń zaznaczone ..."opcja -
list_display_links = None
: unika klikania w kolumny, aby edytować ten obiekt -
has_add_permission()
zwracanie False unika tworzenia nowych obiektów dla tego modelu
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-25 16:28:32
Jeśli zaakceptowana odpowiedź nie działa dla ciebie, spróbuj tego:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-08 08:45:42
Kompilacja doskonałych odpowiedzi @darklow i @ josir, plus dodanie nieco więcej, aby usunąć przyciski "Zapisz" i "zapisz i kontynuuj" prowadzi do (w składni Pythona 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
A potem używasz jak
class MyModelAdmin(ReadOnlyAdmin):
pass
Próbowałem tego tylko z Django 1.11 / Python 3.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-18 14:46:53
Zaakceptowana odpowiedź powinna działać, ale zachowa to również kolejność wyświetlania pól readonly. Nie musisz również kodować na twardo modelu za pomocą tego rozwiązania.
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-16 02:44:33
Spotkałem się z tym samym wymogiem, gdy potrzebowałem aby wszystkie pola były tylko odczytywane dla niektórych użytkowników w django admin skończyło się na wykorzystaniu modułu django "django-admin-view-permission" bez włączania własnego kodu. Jeśli potrzebujesz bardziej drobnoziarnistej kontroli, aby jawnie zdefiniować, które pola, musisz rozszerzyć moduł. Możesz sprawdzić wtyczkę w działaniu tutaj
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-20 04:45:14
To zostało dodane do Django 2.1, które zostało wydane 8/1/18!
ModelAdmin.has_view_permission()
jest podobnie jak istniejące has_delete_permission, has_change_permission i has_add_permission. Możesz o tym przeczytać w dokumentach tutaj
Z informacji o wydaniu:
Pozwala to dać użytkownikom dostęp tylko do odczytu do modeli w panelu administracyjnym. ModelAdmin.has_view_permission() jest nowe. Realizacja jest kompatybilne wstecz, ponieważ nie ma potrzeby przypisywania " widoku" pozwolenie aby umożliwić użytkownikom, którzy mają uprawnienia "Zmień", edytowanie obiektów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-01 19:40:55
Read-only => views permission
pipenv install django-admin-view-permission
- Dodaj 'admin_view_permission' do INSTALLED_APPS w Ustawieniach. py. w ten sposób: "INSTALLED_APPS = [ "admin_view_permission",
- python manage.py migrate
- python manage.py runserver
6666
Ok.baw się dobrze z uprawnieniami "views"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-12 07:00:52
Napisałem klasę generyczną do obsługi ReadOnly view w zależności od uprawnień użytkownika, w tym linii;)
W 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
W 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 )
Wtedy możemy po prostu dziedziczyć Normalnie nasze klasy w admin.py:
class ContactAdmin(ReadOnlyAdmin):
list_display = ("name","email","whatever")
readonly_fields = ("updated","created")
inlines = ( PhoneInline, ... )
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-11 18:11:58