140
Based on x0nix’s answer I did some experiments. It seems like returning an empty dict from get_model_perms
excludes the model from index.html, whilst still allowing you to edit instances directly.
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)
51
For Django 1.8 and above
Since Django 1.8, ModelAdmin
has got a new method called has_module_permission()
which is responsible for displaying a model in admin index.
To hide a model from admin index, just create this method in your ModelAdmin
class and return False
. Example:
class MyModelAdmin(admin.ModelAdmin):
...
def has_module_permission(self, request):
return False
- [Django]-How to query as GROUP BY in Django?
- [Django]-Row level permissions in django
- [Django]-Foreign key from one app into another in Django
24
Got the same problem, here what I came up with.
Like in previous solution – copy index.html from django to your /admin/index.html and modify it like this:
{% for model in app.models %}
{% if not model.perms.list_hide %}
<tr>
...
</tr>
{% endif %}
{% endfor %}
And create ModelAdmin subclass:
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
Now any model registered with HiddenModelAdmin subclass won’t show up in admin list, but will be available via “plus” symbol in detail:
class MyModelAdmin(HiddenModelAdmin):
...
admin.site.register(MyModel, MyModelAdmin)
- [Django]-What is a django.utils.functional.__proxy__ object and what it helps with?
- [Django]-Django delete FileField
- [Django]-Handling race condition in model.save()
3
As of Django 1.8.18, has_module_permission()
still has issue. So, in our case we used also the get_model_perms()
. Likewise, we need to hide the model for specific user only, but the superuser
should be able to access its index entry.
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)
- [Django]-Reload django object from database
- [Django]-How to run celery as a daemon in production?
- [Django]-How to manage local vs production settings in Django?
1
Ugly solution: override admin index template i.e. copy index.html from django to your /admin/index.html and add something like this:
{% for for model in app.models %}
{% ifnotequal model.name "NameOfModelToHide" %}
...
- [Django]-Django render_to_string missing information
- [Django]-What is the max size of 'max_length' in Django?
- [Django]-Django – Clean permission table
1
This is an alternative building on top x0nix’s answer, and only if you are happy hiding the the rows with jquery.
Copy pasting from the other answer the part that I reused
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)
Then install django-jquery and then add the following block in your /admin/index.html
template:
{% 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 %}
You don’t need to copy paste the whole template, just extend it and override the extrahead
block. You’ll need django-apptemplates for the above to work.
- [Django]-Setting the selected value on a Django forms.ChoiceField
- [Django]-Table thumbnail_kvstore doesn't exist
- [Django]-Running Django with FastCGI or with mod_python
1
I had lots of model admins to register and hide, if you want a more DRY solution, this worked for me (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)
I guess you could roll it into a utility class if you want to re-use it across apps.
- [Django]-Django: multiple models in one template using forms
- [Django]-How to filter empty or NULL names in a QuerySet?
- [Django]-What does on_delete do on Django models?
1
Only don’t put admin.site.register(MyModel, MyModelAdmin) in admin.py for example. Register the model normaly.
- [Django]-How to use "get_or_create()" in Django?
- [Django]-How to access array elements in a Django template?
- [Django]-Suddenly when running tests I get "TypeError: 'NoneType' object is not iterable
0
Django 1.2 has new if-statements, meaning that the desired feature could be obtained only by overwriting admin/index.html
{% if model.name not in "Name of hidden model; Name of other hidden model" %}
...
{% endif %}
This is a bad solution, because it doesn’t care about multi-language admins. You could of course add the names of models in all of the supported languages. It’s a good solution because it doesn’t overwrite more than one aspect of core Django functions.
But before changing anything, I think people should think about this…
Essentially the problem is related to having models that one does not wish to use for more than adding an option to a drop-down once in a while. It could effectively be worked around by creating a set of permissions for “not so advanced” users that panic when there are too many models. In case changes in the particular models are required, one can simply log in with the “advanced account”.
- [Django]-Get protocol + host name from URL
- [Django]-How to get the current language in Django?
- [Django]-Django: How to get related objects of a queryset?