Django admin, esconda um modelo

87

Na página raiz do site de administração onde os modelos registrados aparecem, desejo ocultar vários modelos que estão registrados no administrador do Django.

Se eu cancelar o registro diretamente, não poderei adicionar novos registros, pois o símbolo de adicionar novo "+" desaparece.

Como isso pode ser feito ?

Hellnar
fonte

Respostas:

124

Com base na resposta de x0nix, fiz alguns experimentos. Parece que retornar um dicionário vazio de get_model_permsexclui o modelo de index.html, embora ainda permita que você edite instâncias diretamente.

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
fonte
Acordado. Só que isso é um problema quando não quero alterar o código. O que quero dizer é que tenho um aplicativo básico que quero manter limpo das dependências de outros aplicativos. Eu mantenho essas dependências em um aplicativo derivado específico do projeto. Agora, quero que a interface administrativa mostre apenas o aplicativo derivado, não o aplicativo base. Django requer que o aplicativo base seja listado em settings / INSTALLED_APPS para que o aplicativo derivado funcione. Obviamente, o aplicativo base não deve ser mostrado, mas ao mesmo tempo não quero mantê-lo inalterado e reutilizável. Veja [aqui] ( Stack Exchange / questions / 13923968 /).
Sven de
6
Um caminho mais curto:get_model_perms = lambda self, req: {}
Tigran Saluev
3
E se eu quiser ocultar um modelo de um certo userAdmin?
Alireza Sanaee
1
Tenha cuidado com esta solução - mesmo que o link desapareça, o usuário pode pular para o próprio objeto como este: / admin / main / comment / 2333 / change /
goodgrief
35

Para Django 1.8 e superior

Desde Django 1.8, ModelAdmintem um novo método chamado has_module_permission()que é responsável por exibir um modelo no índice de administração.

Para ocultar um modelo do índice de administração, basta criar este método em sua ModelAdminclasse e retornarFalse . Exemplo:

class MyModelAdmin(admin.ModelAdmin):
    ...
    def has_module_permission(self, request):
        return False
xyres
fonte
Infelizmente has_module_permissionafeta todo o aplicativo e não apenas um modelo. Portanto, adicionar isso a um modelo no aplicativo causa um 403 Proibido na lista de modelos de aplicativos (/ admin / app_label /). Veja django / contrib / admin / sites.py .
Fabian
1
@Fabian acho que é um bug. Eu perguntei isso no canal IRC do Django, e algumas pessoas concordam que esse comportamento é indesejado.
xyres
@Fabian Supondo que a página de índice do administrador ainda tenha links para / admin / , é possível contornar esse bug por algo semelhante return request.path!='/admin/'. Infelizmente, isso reativa esses modelos na lista de modelos de aplicativos.
ecp
Eu tinha aberto um tíquete aqui para esse bug. Isso foi corrigido aqui . Deve ser incluído na próxima versão, espero.
xyres de
No Django 1.11, o link direto ainda funciona, mas a entidade não está listada na tela principal do administrador
Csaba Toth
22

Tenho o mesmo problema, aqui está o que eu vim.

Como na solução anterior - copie index.html do django para o seu /admin/index.html e modifique-o assim:

{% for model in app.models %}
    {% if not model.perms.list_hide %}
    <tr>
    ...
    </tr>
    {% endif %}
{% endfor %}

E crie a subclasse 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

Agora, qualquer modelo registrado com a subclasse HiddenModelAdmin não aparecerá na lista de administradores, mas estará disponível por meio do símbolo "mais" em detalhes:

class MyModelAdmin(HiddenModelAdmin):
    ...

admin.site.register(MyModel, MyModelAdmin)
x0nix
fonte
1

Solução feia: substitua o modelo de índice do administrador, ou seja, copie index.html do django para o seu /admin/index.html e adicione algo como isto:

{% for for model in app.models %}
    {% ifnotequal model.name "NameOfModelToHide" %}
    ...
alex vasi
fonte
1

Esta é uma construção alternativa sobre a resposta do x0nix, e somente se você estiver satisfeito em ocultar as linhas com jquery.

Copie colando da outra resposta a parte que eu reaprovei

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)

Em seguida, instale django-jquery e adicione o seguinte bloco em seu /admin/index.htmlmodelo:

{% 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 %}

Você não precisa copiar e colar todo o modelo, apenas estenda-o e substitua o extraheadbloco. Você precisará do django-apptemplates para que o procedimento acima funcione.

Panos
fonte
0

Django 1.2 tem novas instruções if, o que significa que o recurso desejado só pode ser obtido sobrescrevendo admin / index.html

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

Esta é uma solução ruim, porque não se preocupa com administradores multilíngues. Você pode, é claro, adicionar os nomes dos modelos em todos os idiomas suportados. É uma boa solução porque não sobrescreve mais de um aspecto das funções principais do Django.

Mas antes de mudar qualquer coisa, acho que as pessoas deveriam pensar nisso ...

Essencialmente, o problema está relacionado a ter modelos que não se deseja usar além de adicionar uma opção a um menu suspenso de vez em quando. Isso poderia ser contornado com eficácia criando um conjunto de permissões para usuários "não tão avançados" que entram em pânico quando há muitos modelos. Caso sejam necessárias alterações nos modelos específicos, pode-se simplesmente fazer o login com a "conta avançada".

Benjaoming
fonte
0

Tive muitos administradores de modelo para registrar e ocultar, se você quiser uma solução mais DRY, funcionou para mim (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)

Eu acho que você poderia incluí-lo em uma classe de utilitário se quiser reutilizá-lo em todos os aplicativos.

murraybiscuit
fonte
0

No Django 1.8.18 , has_module_permission()ainda tem problemas. Portanto, no nosso caso, usamos também o get_model_perms(). Da mesma forma, precisamos ocultar o modelo apenas para um usuário específico, mas superuserdeve ser capaz de acessar sua entrada de índice.

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)
Ranel Padon
fonte