Django admin, скрыть модель

На корневой странице сайта администратора, где появились зарегистрированные модели, я хочу скрыть несколько моделей, зарегистрированных в администраторе Django.

Если я напрямую их отменил, я не могу добавить новые записи, так как новый символ "+" исчезает.

Как это можно сделать?

Ответ 1

На основе x0nix answer Я сделал несколько экспериментов. Кажется, что возврат пустой dict из 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)

Ответ 2

Получилась та же проблема, вот что я придумал.

Как и в предыдущем решении - скопируйте index.html из django в свой /admin/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)

Ответ 3

Так как Django 1.8, ModelAdmin получил новый метод has_module_permission(), который отвечает за отображение модели в индексе администратора.

Чтобы скрыть модель из индекса администратора, просто создайте этот метод в своем классе ModelAdmin и верните False. Пример:

class MyModelAdmin(admin.ModelAdmin):
    ...
    def has_module_permission(self, request):
        return False

Ответ 4

Ужасное решение: переопределить шаблон индекса администратора, т.е. скопировать index.html из django в ваш /admin/index.html и добавить что-то вроде этого

{% for for model in app.models %}
    {% ifnotequal model.name "NameOfModelToHide" %}
    ...

Ответ 5

Это альтернативное здание на вершине 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 для работы выше.

Ответ 6

Django 1.2 имеет новые операторы if, что означает, что желаемая функция может быть получена только путем перезаписи admin/index.html

{% if model.name not in "Name of hidden model; Name of other hidden model" %}
    ...
{% endif %}

Это плохое решение, потому что его не интересуют многоязычные администраторы. Конечно, вы могли бы добавить имена моделей на всех поддерживаемых языках. Это хорошее решение, потому что оно не перезаписывает более одного аспекта основных функций Django.

Но прежде чем что-либо менять, я думаю, люди должны подумать об этом...

По существу проблема связана с наличием моделей, которые вы не хотите использовать, вместо добавления опции в раскрывающееся меню. Его можно эффективно обойти, создав набор разрешений для "не очень продвинутых" пользователей, которые паникуют, когда слишком много моделей. В случае необходимости изменений в конкретных моделях можно просто войти в систему с помощью "расширенной учетной записи".

Ответ 7

У меня было много администраторов моделей для регистрации и скрытия, если вы хотите более 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)

Я думаю, вы могли бы перевернуть его в класс утилиты, если хотите повторно использовать его в приложениях.

Ответ 8

По состоянию на 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)