Django admin, hide a model

DjangoDjango Admin

Django Problem Overview


At the root page of the admin site where registered models appear, I want to hide several models that are registered to the Django admin.

If I directly unregister those, I am not able to add new records as the add new symbol "+" dissapears.

How can this be done ?

Django Solutions


Solution 1 - Django

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)

Solution 2 - Django

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

Solution 3 - Django

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)

Solution 4 - Django

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)

Solution 5 - Django

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" %}
    ...

Solution 6 - Django

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.

Solution 7 - Django

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.

Solution 8 - Django

Only don't put admin.site.register(MyModel, MyModelAdmin) in admin.py for example. Register the model normaly.

Solution 9 - Django

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".

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHellnarView Question on Stackoverflow
Solution 1 - DjangoshaunsephtonView Answer on Stackoverflow
Solution 2 - DjangoxyresView Answer on Stackoverflow
Solution 3 - Djangox0nixView Answer on Stackoverflow
Solution 4 - DjangoRanel PadonView Answer on Stackoverflow
Solution 5 - Djangoalex vasiView Answer on Stackoverflow
Solution 6 - DjangoPanosView Answer on Stackoverflow
Solution 7 - DjangomurraybiscuitView Answer on Stackoverflow
Solution 8 - DjangoRoberta MeirelesView Answer on Stackoverflow
Solution 9 - DjangobenjaomingView Answer on Stackoverflow