Администратор Django, скрыть модель

87

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

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

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

Hellnar
источник

Ответы:

124

Основываясь на ответе x0nix, я провел несколько экспериментов. Похоже, что возврат пустого 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)
Shaunsephton
источник
Согласовано. Только вот проблема, когда я не хочу менять код. Я имею в виду, что у меня есть базовое приложение, которое я хочу уберечь от зависимостей от других приложений. Я сохраняю эти зависимости в производном приложении для конкретного проекта. Теперь я хочу, чтобы в интерфейсе администратора отображалось только производное приложение, а не базовое. Django требует, чтобы базовое приложение было указано в settings / INSTALLED_APPS, чтобы производное приложение работало. Очевидно, что базовое приложение не должно отображаться, но в то же время я не хочу оставлять его неизменным и многоразовым. См. [Здесь] ( Stack Exchange / questions / 13923968 /).
Sven
6
Более короткий путь:get_model_perms = lambda self, req: {}
Тигран Салуев
3
Что, если я хочу скрыть модель от определенного userAdmin?
Алиреза Санаи
1
Будьте осторожны с этим решением - даже если ссылка исчезнет, ​​пользователь может перейти к самому объекту следующим образом: / admin / main / comment / 2333 / change /
goodgrief
35

Для Django 1.8 и выше

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

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

class MyModelAdmin(admin.ModelAdmin):
    ...
    def has_module_permission(self, request):
        return False
xyres
источник
К сожалению, has_module_permissionвлияет на все приложение, а не только на одну модель. Таким образом, добавление этого в модель в приложении вызывает 403 Запрещено в списке моделей приложения (/ admin / app_label /). См. Django / contrib / admin / sites.py .
Fabian
1
@Fabian Я думаю, что это ошибка. Я спросил об этом на IRC-канале Django, и некоторые люди согласны с тем, что такое поведение нежелательно.
xyres
@Fabian Предполагая, что страница индекса администратора по-прежнему ссылается на / admin /, можно обойти эту ошибку чем-то вроде return request.path!='/admin/'. К сожалению, это повторно активирует эти модели в списке моделей приложения.
ecp
Я открыл здесь заявку на эту ошибку. Это было исправлено здесь . Надеюсь, он будет включен в следующий выпуск.
xyres
В Django 1.11 глубокая ссылка по-прежнему работает, но объект не указан на главном экране администратора
Чаба Тот
22

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

Как и в предыдущем решении - скопируйте 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)
x0nix
источник
1

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

{% for for model in app.models %}
    {% ifnotequal model.name "NameOfModelToHide" %}
    ...
Алекс Васи
источник
1

Это альтернативное построение поверх ответа 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 .

Панос
источник
0

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

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

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

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

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

Benjaoming
источник
0

У меня было много администраторов моделей для регистрации и скрытия, если вам нужно более СУХИЕ решение, это сработало для меня (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)

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

Мюррей
источник
0

Начиная с 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)
Ранел Падон
источник