L'histoire du modèle de Django Admin

Le Programme D'Installation:

  • je travaille sur une application Django qui permet aux utilisateurs de créer un objet dans la base de données, puis de revenir en arrière et de l'éditer autant qu'ils le désirent.
  • le site admin de Django conserve un historique des modifications apportées aux objets via le site admin.

La Question:

  • Comment puis-je brancher mon application à l'historique des changements du site administrateur pour que je puisse voir l'historique des changements que les utilisateurs font à leur "contenu"?
80
demandé sur ghickman 2009-06-12 20:32:47

5 réponses

l'historique admin est juste une application comme n'importe quelle autre application Django, à l'exception d'un placement spécial sur le site admin.

le modèle est à django.contrib.admin.modèle.LogEntry.

quand un utilisateur fait un changement, ajouter au journal comme ceci (volé sans vergogne contrib/admin/options.py:

from django.contrib.admin.models import LogEntry, ADDITION
LogEntry.objects.log_action(
    user_id         = request.user.pk, 
    content_type_id = ContentType.objects.get_for_model(object).pk,
    object_id       = object.pk,
    object_repr     = force_unicode(object), 
    action_flag     = ADDITION
)

object est l'objet qui a été changé bien sûr.

maintenant je vois Daniel réponse et d'accord avec lui, il est assez limité.

à mon avis, Une approche plus forte est d'utiliser le code de Marty Alchin dans son livre Pro Django (voir conservation des archives historiques à partir de la page 263). Il existe une application django-simple-history qui implémente et étend cette approche ( docs here ).

118
répondu Van Gale 2015-01-07 12:03:27

le journal d'historique des changements de l'administrateur est défini dans django.contrib.admin.models , et il y a une méthode history_view dans la classe standard ModelAdmin .

ils ne sont pas particulièrement astucieux cependant, et assez étroitement couplé à l'administrateur, de sorte que vous pouvez être mieux en utilisant simplement ces idées et de créer votre propre version pour votre application.

21
répondu Daniel Roseman 2009-06-12 18:13:39

je sais que cette question Est ancienne, mais à partir d'aujourd'hui (Django 1.9), les éléments de L'histoire de Django sont plus robustes qu'ils ne l'étaient à la date de cette question. Dans un projet en cours, j'avais besoin d'obtenir les éléments de l'histoire récente et les mettre dans un dropdown de la barre de navigation. C'est ainsi que je l'ai fait et j'ai été très direct:

*views.py*    

from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION

def main(request, template):

    logs = LogEntry.objects.exclude(change_message="No fields changed.").order_by('-action_time')[:20]
    logCount = LogEntry.objects.exclude(change_message="No fields changed.").order_by('-action_time')[:20].count()

    return render(request, template, {"logs":logs, "logCount":logCount})

comme vu dans l'extrait de code ci-dessus, je crée un queseryset de base à partir du modèle LogEntry (django.contrib.admin.models.py c'est où c'est situé à django 1.9) et à l'exclusion des articles pour lesquels aucun changement n'est prévu, en ordonnant le tout au plus tard au moment de l'action et en ne montrant que les 20 derniers logs. J'ai aussi un autre objet avec juste le comte. Si vous regardez le modèle LogEntry, vous pouvez voir les noms de champ que Django a utilisé afin de retirer les morceaux de données dont vous avez besoin. Pour mon cas spécifique, voici ce que j'ai utilisé dans mon modèle:

lien vers L'Image du produit Final

*template.html*

<ul class="dropdown-menu">
    <li class="external">
        <h3><span class="bold">{{ logCount }}</span> Notification(s) </h3>
        <a href="{% url 'index' %}"> View All </a>
    </li>
        {% if logs %}
            <ul class="dropdown-menu-list scroller actionlist" data-handle-color="#637283" style="height: 250px;">
                {% for log in logs %}
                    <li>
                        <a href="javascript:;">
                            <span class="time">{{ log.action_time|date:"m/d/Y - g:ia" }} </span>
                            <span class="details">
                                {% if log.action_flag == 1 %}
                                    <span class="label label-sm label-icon label-success">
                                        <i class="fa fa-plus"></i>
                                    </span>
                                {% elif log.action_flag == 2 %}
                                    <span class="label label-sm label-icon label-info">
                                        <i class="fa fa-edit"></i>
                                    </span>
                                {% elif log.action_flag == 3 %}
                                    <span class="label label-sm label-icon label-danger">
                                        <i class="fa fa-minus"></i>
                                    </span>
                                {% endif %}
                                {{ log.content_type|capfirst }}: {{ log }}
                            </span>
                        </a>
                    </li>
                 {% endfor %}
            </ul>
        {% else %}
            <p>{% trans "This object doesn't have a change history. It probably wasn't added via this admin site." %}</p>
        {% endif %}
    </li>
</ul>
9
répondu dave4jr 2016-03-06 21:58:58

pour ajouter à ce qui a déjà été dit, Voici d'autres ressources pour vous:

(1): j'ai travaillé avec une application appelée django-retour qui "crochets" l'administrateur de l'histoire et ajoute réellement à elle. Si vous vouliez un exemple de code qui serait un bon endroit pour chercher.

(2) Si vous décidez de lancer votre propre fonctionnalité d'histoire django fournit des signaux auxquels vous pouvez vous abonner pour avoir votre gestion d'application, pour exemple: post_save pour chaque objet history. Votre code serait exécuté chaque fois qu'une entrée de journal d'histoire a été sauvée. Doc: Django "signaux de 151940920"

7
répondu T. Stone 2009-07-31 00:16:21

Exemple De Code

Bonjour,

j'ai récemment piraté certaines opérations de journalisation dans une vue" update " pour notre base de données d'inventaire de serveur. J'ai pensé que je partagerais mon code "exemple". La fonction qui suit prend un de nos objets "Server", une liste des choses qui ont été changées, et un champ action_flag D'ADDITION ou de modification. Il simplifie les choses un tout petit peu où ajout signifie "ajout d'un nouveau serveur."Une approche plus souple permettrait l'ajout d' un attribut à un serveur. Bien sûr, il était suffisamment difficile de vérifier nos fonctions existantes pour déterminer si un changement avait effectivement eu lieu, donc je suis assez heureux d'enregistrer de nouveaux attributs comme un "changement".

from django.contrib.admin.models import LogEntry, User, ADDITION, CHANGE
from django.contrib.contenttypes.models import ContentType

def update_server_admin_log(server, updated_list, action_flag):
    """Log changes to Admin log."""
    if updated_list or action_flag == ADDITION:
        if action_flag == ADDITION:
            change_message = "Added server %s with hostname %s." % (server.serial, server.name)
        # http://dannyman.toldme.com/2010/06/30/python-list-comma-comma-and/
        elif len(updated_list) > 1:
            change_message = "Changed " + ", ".join(map(str, updated_list[:-1])) + " and " + updated_list[-1] + "."
        else:
            change_message = "Changed " + updated_list[0] + "."
        # /q/tying-in-to-django-admin-s-model-history-37193/"update" user added just for this purpose -- you probably want request.user.id
                user_id = User.objects.get(username='update').id,
                content_type_id = ContentType.objects.get_for_model(server).id,
                object_id = server.id,
                # HW serial number of our local "Server" object -- definitely change when adapting ;)
                object_repr = server.serial,
                change_message = change_message,
                action_flag = action_flag,
                )
        except:
            print "Failed to log action."
2
répondu dannyman 2010-07-07 13:25:21