Адміністратор Django, приховати модель


85

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

Якщо я реєструю їх безпосередньо, я не можу додавати нові записи, оскільки додавання нового символу "+" зникає.

Як це можна зробити?

Відповіді:


123

На основі відповіді 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)

Домовились. Тільки це проблема, коли я не хочу змінювати код. Я маю на увазі, що у мене є базовий додаток, який я хочу тримати в чистоті від залежностей інших програм. Я зберігаю ці залежності у похідному додатку для конкретного проекту. Тепер я хочу, щоб інтерфейс адміністратора відображав лише похідну програму, а не базову програму. Django вимагає, щоб базова програма була вказана в налаштуваннях / INSTALLED_APPS, щоб похідна програма працювала. Очевидно, що базова програма не повинна відображатися, але в той же час я не хочу залишати її немодифікованою та багаторазовою. Дивіться [тут] ( Stack Exchange / questions / 13923968 /).
Свен

6
Коротший шлях:get_model_perms = lambda self, req: {}
Тигран Салуєв

2
Що робити, якщо я хочу приховати модель від певного користувачаAdmin?
Alireza Sanaee

1
Будьте обережні з цим рішенням - навіть якщо посилання зникає, користувач може перейти до самого об’єкта так: / admin / main / comment / 2333 / change /
goodgrief

32

Для Django 1.8 і вище

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

Щоб приховати модель з індексу адміністратора, просто створіть цей метод у своєму ModelAdminкласі та поверніться False. Приклад:

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

На жаль, це has_module_permissionвпливає на весь додаток, а не лише на одну модель. Тож додавання цього до моделі в додатку спричиняє 403 Заборонено у списку моделей програми (/ admin / app_label /). Див. Django / contrib / admin / sites.py .
Фабіан

1
@Fabian Я думаю, що це помилка. Я запитав це на IRC-каналі Django, і деякі люди там погоджуються, що така поведінка є небажаною.
xyres

@Fabian Припускаючи, що сторінка індексу адміністратора все ще посилається на / admin / можна обійти цю помилку чимось на зразок return request.path!='/admin/'. На жаль, це знову вмикає ці моделі у списку моделей додатків.
ecp

Я відкрив тут квиток на цю помилку. Це тут виправлено . Сподіваємось, його слід включити до наступного випуску.
xyres

У Django 1.11 пряме посилання все ще працює, але сутність не вказана на головному екрані адміністратора
Csaba Toth

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)

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


0

Django 1.2 має нові оператори if-, що означає, що бажану функцію можна отримати, лише переписавши admin / index.html

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

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

Але перш ніж щось змінювати, я думаю, людям слід подумати про це ...

По суті, проблема пов’язана з наявністю моделей, які людина не бажає використовувати більше, ніж час від часу додавати опцію до випадаючого меню. Його можна ефективно обійти, створивши набір дозволів для "не настільки просунутих" користувачів, які панікують, коли моделей занадто багато. Якщо потрібні зміни в конкретних моделях, можна просто увійти за допомогою «розширеного облікового запису».


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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.