登録されたモデルが表示される管理サイトのルートページで、Django adminに登録されているいくつかのモデルを非表示にしたい。
それらを直接登録解除すると、新しい記号「+」が表示されなくなるため、新しいレコードを追加できません。
これはどのように行うことができますか?
x0nixの答え に基づいて、いくつかの実験を行いました。 get_model_perms
から空の辞書を返すと、index.htmlからモデルが除外されますが、インスタンスを直接編集することはできます。
class MyModelAdmin(admin.ModelAdmin):
def get_model_perms(self, request):
"""
Return empty perms dict thus hiding the model from admin index.
"""
return {}
admin.site.register(MyModel, MyModelAdmin)
ここで私が思いついたのは、同じ問題です。
前のソリューションと同じように、Djangoから/admin/index.htmlにindex.htmlをコピーし、次のように変更します。
{% for model in app.models %}
{% if not model.perms.list_hide %}
<tr>
...
</tr>
{% endif %}
{% endfor %}
そして、ModelAdminサブクラスを作成します。
class HiddenModelAdmin(admin.ModelAdmin):
def get_model_perms(self, *args, **kwargs):
perms = admin.ModelAdmin.get_model_perms(self, *args, **kwargs)
perms['list_hide'] = True
return perms
HiddenModelAdminサブクラスに登録されたモデルは管理リストに表示されなくなりますが、「プラス」記号を使用して詳細に利用できます。
class MyModelAdmin(HiddenModelAdmin):
...
admin.site.register(MyModel, MyModelAdmin)
Django 1.8以降、ModelAdmin
には has_module_permission()
という新しいメソッドが追加されました。これは、管理者インデックスでモデルを表示することを担当します。
管理インデックスからモデルを非表示にするには、ModelAdmin
クラスでこのメソッドを作成し、False
を返します。例:
class MyModelAdmin(admin.ModelAdmin):
...
def has_module_permission(self, request):
return False
これは、上位のx0nixの答えを基にした代替の構築であり、jqueryで行を非表示にして満足している場合のみです。
再利用した部分を他の回答からコピー貼り付け
class HiddenModelAdmin(admin.ModelAdmin):
def get_model_perms(self, *args, **kwargs):
perms = admin.ModelAdmin.get_model_perms(self, *args, **kwargs)
perms['list_hide'] = True
return perms
class MyModelAdmin(HiddenModelAdmin):
...
admin.site.register(MyModel, MyModelAdmin)
次に Django-jquery をインストールし、/admin/index.html
テンプレートに次のブロックを追加します。
{% extends "admin:admin/index.html" %}
{% block extrahead %}
<script type="text/javascript" src="{{ STATIC_URL }}js/jquery.js"></script>
{% if app_list %}
<script type="text/javascript">
$(function(){
{% for app in app_list %}
{% for model in app.models %}
{% if model.perms.list_hide %}
$('div.app-{{ app.app_label }}').find('tr.model-{{ model.object_name|lower }}').hide();
{% endif %}
{% endfor %}
{% endfor %}
});
</script>
{% endif %}
{% endblock %}
テンプレート全体をコピーして貼り付ける必要はありません。テンプレートを拡張してextrahead
ブロックをオーバーライドするだけです。上記を機能させるには Django-apptemplates が必要です。
醜い解決策: override admin index templateつまり、index.htmlをDjangoから/admin/index.htmlにコピーし、次のようなものを追加します。
{% for for model in app.models %}
{% ifnotequal model.name "NameOfModelToHide" %}
...
たくさんのモデル管理者を登録して非表示にしたので、より多くのDRYソリューションが必要な場合は、これでうまくいきました(Django 1.10、Python 3.5)
# admin.py
def register_hidden_models(*model_names):
for m in model_names:
ma = type(
str(m)+'Admin',
(admin.ModelAdmin,),
{
'get_model_perms': lambda self, request: {}
})
admin.site.register(m, ma)
register_hidden_models(MyModel1, MyModel2, MyModel3)
アプリ間で再利用したい場合は、ユーティリティクラスにまとめることができると思います。
Django 1.2には新しいifステートメントが含まれています。つまり、admin/index.htmlを上書きすることによってのみ目的の機能を取得できます
{% if model.name not in "Name of hidden model; Name of other hidden model" %}
...
{% endif %}
多言語の管理者を気にしないので、これは悪いソリューションです。もちろん、サポートされているすべての言語でモデルの名前を追加することもできます。コアDjango関数の複数の側面を上書きしないため、これは優れたソリューションです。
しかし、何かを変える前に、人々はこれについて考えるべきだと思います...
基本的に、問題は、ドロップダウンにオプションを追加すること以外に使用したくないモデルがあることに関連しています。モデルが多すぎるときにパニックを起こす「それほど高度ではない」ユーザー向けの一連の権限を作成することで、効果的に回避できます。特定のモデルの変更が必要な場合は、「高度なアカウント」で簡単にログインできます。
Django 1.8.18の時点で、has_module_permission()
にはまだ問題があります。そのため、このケースではget_model_perms()
も使用しました。同様に、特定のユーザーに対してのみモデルを非表示にする必要がありますが、superuser
はそのインデックスエントリにアクセスできる必要があります。
class MyModelAdmin(admin.ModelAdmin):
def get_model_perms(self, request):
if not request.user.is_superuser:
return {}
return super(MyModelAdmin, self).get_model_perms(request)
admin.site.register(MyModel, MyModelAdmin)