Bagaimana cara membuat model sepenuhnya hanya-baca di antarmuka admin? Ini untuk semacam tabel log, di mana saya menggunakan fitur admin untuk mencari, mengurutkan, memfilter, dll., Tetapi tidak perlu mengubah log.
Jika ini terlihat seperti duplikat, ini bukan yang saya coba lakukan:
- Saya tidak mencari bidang hanya baca (bahkan membuat setiap bidang hanya dapat dibaca tetap memungkinkan Anda membuat catatan baru)
- Saya tidak ingin membuat pengguna hanya- baca : setiap pengguna harus hanya-baca.
django
django-admin
readonly
Steve Bennett
sumber
sumber
has_view_permission
akhirnya diimplementasikan di Django 2.1. Lihat juga stackoverflow.com/a/51641149 di bawah.Jawaban:
Lihat 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 (untuk 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 %}
sumber
Model
, atau untukModelAdmin
?ModelAdmin
.Admin untuk mengedit, tidak hanya melihat (Anda tidak akan menemukan izin "melihat"). Untuk mencapai apa yang Anda inginkan, Anda harus melarang penambahan, penghapusan, dan membuat semua bidang hanya-baca:
class MyAdmin(ModelAdmin): def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False
(jika Anda melarang perubahan, Anda bahkan tidak akan bisa melihat objeknya)
Untuk beberapa kode yang belum teruji yang mencoba mengotomatiskan pengaturan semua bidang hanya-baca, lihat jawaban saya untuk Model utuh sebagai hanya-baca
EDIT: juga belum teruji tetapi baru saja melihat LogEntryAdmin saya dan itu
readonly_fields = MyModel._meta.get_all_field_names()
Tidak tahu apakah itu akan berhasil dalam semua kasus.
EDIT: QuerySet.delete () mungkin masih menghapus objek secara massal. Untuk menyiasati ini, sediakan pengelola "objek" Anda sendiri dan subkelas QuerySet terkait yang tidak menghapus - lihat Mengganti QuerySet.delete () di Django
sumber
Berikut adalah dua kelas yang saya gunakan untuk membuat model dan / atau sebaris hanya untuk dibaca.
Untuk admin model:
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
Untuk sebaris:
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
sumber
has_add_permission
inReadOnlyAdmin
hanya menerima permintaan sebagai parameterJika Anda ingin pengguna menyadari bahwa dia tidak dapat mengeditnya, 2 bagian hilang pada solusi pertama. Anda telah menghapus tindakan hapus!
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
Kedua: solusi hanya baca berfungsi dengan baik pada model biasa. Tetapi TIDAK berfungsi jika Anda memiliki model yang diwariskan dengan kunci asing. Sayangnya, saya belum tahu solusinya. Upaya yang baik adalah:
Seluruh model sebagai read-only
Tapi itu juga tidak berhasil untuk saya.
Dan catatan terakhir, jika Anda ingin memikirkan solusi yang luas, Anda harus memastikan bahwa setiap inline juga harus hanya dapat dibaca.
sumber
Sebenarnya Anda bisa mencoba solusi sederhana ini:
class ReadOnlyModelAdmin(admin.ModelAdmin): actions = None list_display_links = None # more stuff here def has_add_permission(self, request): return False
actions = None
: hindari menampilkan tarik-turun dengan opsi "Hapus yang dipilih ..."list_display_links = None
: menghindari mengklik kolom untuk mengedit objek ituhas_add_permission()
return False menghindari pembuatan objek baru untuk model itusumber
Ini ditambahkan ke Django 2.1 yang dirilis pada 8/1/18!
ModelAdmin.has_view_permission()
seperti izin has_delete_permission, has_change_permission, dan has_add_permission yang ada. Anda dapat membacanya di dokumen di siniDari catatan rilis:
sumber
Jika jawaban yang diterima tidak berhasil untuk Anda, coba ini:
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
sumber
Mengompilasi jawaban luar biasa @darklow dan @josir, ditambah menambahkan sedikit lagi untuk menghapus "Simpan" dan tombol "Simpan dan Lanjutkan" mengarah ke (dengan sintaks 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
dan kemudian Anda menggunakan suka
class MyModelAdmin(ReadOnlyAdmin): pass
Saya hanya mencoba ini dengan Django 1.11 / Python 3.
sumber
Jawaban yang diterima seharusnya berfungsi, tetapi ini juga akan mempertahankan urutan tampilan bidang hanya baca. Anda juga tidak perlu melakukan hardcode model dengan solusi ini.
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
sumber
Dengan Django 2.2 saya melakukannya seperti ini:
@admin.register(MyModel) class MyAdmin(admin.ModelAdmin): readonly_fields = ('all', 'the', 'necessary', 'fields') actions = None # Removes the default delete action in list view def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False
sumber
readonly_fields
danactions
tidak diperlukandengan django 2.2, admin readonly bisa sesederhana:
class ReadOnlyAdminMixin(): def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False class LogEntryAdmin(ReadOnlyAdminMixin, admin.ModelAdmin): list_display = ('id', 'user', 'action_flag', 'content_type', 'object_repr')
sumber
Saya menemukan persyaratan yang sama ketika perlu membuat semua bidang hanya-baca untuk pengguna tertentu di django admin akhirnya memanfaatkan modul django "django-admin-view-izin" tanpa memutar kode saya sendiri. Jika Anda membutuhkan kontrol yang lebih halus untuk secara eksplisit menentukan bidang mana, Anda perlu memperluas modul. Anda dapat melihat plugin beraksi di sini
sumber
read-only => melihat izin
pipenv install django-admin-view-permission
6666
ok. bersenang-senanglah dengan izin 'tampilan'
sumber
Saya telah menulis kelas generik untuk menangani tampilan ReadOnly tergantung pada izin Pengguna, termasuk inlines;)
Di 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
Di 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 )
Kemudian, kita bisa mewarisi secara normal kelas kita di admin.py:
class ContactAdmin(ReadOnlyAdmin): list_display = ("name","email","whatever") readonly_fields = ("updated","created") inlines = ( PhoneInline, ... )
sumber