web-dev-qa-db-fra.com

Django admin, cache un modèle

Sur la page racine du site d'administration où apparaissent les modèles enregistrés, je souhaite masquer plusieurs modèles enregistrés auprès de l'administrateur Django.

Si je désinscris ceux-ci directement, je ne pourrai pas ajouter de nouveaux enregistrements car le nouveau symbole "+" disparaîtra.

Comment cela peut-il être fait ?

72
Hellnar

Basé sur la réponse de x0nix j'ai fait quelques expériences. Il semble que renvoyer un dict vide de get_model_perms exclut le modèle de index.html, tout en vous permettant de modifier directement des instances.

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)
107
shaunsephton

Vous avez le même problème, voici ce que je suis venu avec.

Comme dans la solution précédente - copiez index.html de Django dans votre /admin/index.html et modifiez-le comme suit:

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

Et créez la sous-classe 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

Désormais, tout modèle inscrit dans la sous-classe HiddenModelAdmin n'apparaîtra pas dans la liste des administrateurs, mais sera disponible via le symbole "plus" en détail:

class MyModelAdmin(HiddenModelAdmin):
    ...

admin.site.register(MyModel, MyModelAdmin)
22
x0nix

Depuis Django 1.8, ModelAdmin dispose d'une nouvelle méthode appelée has_module_permission() qui est chargée d'afficher un modèle dans admin index.

Pour masquer un modèle dans admin index, créez simplement cette méthode dans votre classe ModelAdmin et renvoyez False. Exemple:

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

Ceci est une construction alternative sur la réponse de x0nix, et seulement si vous êtes content de cacher les lignes avec jquery.

Copier coller de l’autre répond à la partie que j’ai réutilisée

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)

Ensuite, installez Django-jquery puis ajoutez le bloc suivant dans votre modèle /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 %}

Vous n'avez pas besoin de copier coller tout le modèle, juste de l'étendre et de remplacer le bloc extrahead. Vous aurez besoin de Django-apptemplates pour que ce qui précède fonctionne.

1
Panos

La solution laide: override modèle d’index administratif, par exemple, copie index.html de Django vers votre /admin/index.html et ajoutez ce qui suit:

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

J'ai eu beaucoup d'administrateurs de modèles à enregistrer et à cacher, si vous voulez une solution plus DRY, cela a fonctionné pour moi (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)

J'imagine que vous pouvez l'intégrer à une classe d'utilitaires si vous souhaitez le réutiliser dans des applications.

0
murraybiscuit

Django 1.2 a de nouvelles instructions if, ce qui signifie que la fonctionnalité désirée ne peut être obtenue qu'en écrasant admin/index.html.

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

C'est une mauvaise solution, car il se fiche des administrateurs multilingues. Vous pouvez bien sûr ajouter les noms de modèles dans toutes les langues prises en charge. C'est une bonne solution car elle n'écrase pas plus d'un aspect des fonctions principales de Django.

Mais avant de changer quoi que ce soit, je pense que les gens devraient y penser ...

Le problème est essentiellement lié au fait de disposer de modèles que l'on ne souhaite pas utiliser plus que d'ajouter une option à une liste déroulante de temps en temps. Cela pourrait être efficacement contourné en créant un ensemble de permissions pour les utilisateurs "moins avancés" qui paniquent quand il y a trop de modèles. Si des modifications sont nécessaires dans les modèles, vous pouvez simplement vous connecter avec le "compte avancé".

0
benjaoming

Depuis Django 1.8.18 , has_module_permission() a toujours le même problème. Donc, dans notre cas, nous avons également utilisé la get_model_perms(). De même, nous devons masquer le modèle pour un utilisateur spécifique uniquement, mais superuser devrait pouvoir accéder à son entrée d'index.

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