From 4190f4f39eb470d2a771980131d925b48c4e6f7c Mon Sep 17 00:00:00 2001 From: Jean-Romain Garnier Date: Sat, 25 Apr 2020 12:31:18 +0200 Subject: [PATCH 1/7] Start implementing detailed history for event class --- logs/models.py | 55 ++++++++- logs/templates/logs/detailed_history.html | 2 +- logs/templatetags/logs_extra.py | 3 +- logs/urls.py | 5 - logs/views.py | 104 +++++------------- machines/templates/machines/aff_machines.html | 4 +- templates/buttons/history.html | 6 - users/templates/users/profil.html | 2 +- 8 files changed, 83 insertions(+), 98 deletions(-) diff --git a/logs/models.py b/logs/models.py index acf8771b..112d536f 100644 --- a/logs/models.py +++ b/logs/models.py @@ -92,6 +92,10 @@ class ActionsSearch: return classes +############################ +# Machine history search # +############################ + class MachineHistorySearchEvent: def __init__(self, user, machine, interface, start=None, end=None): """ @@ -280,14 +284,19 @@ class MachineHistorySearch: return self.events +############################ +# Generic history classes # +############################ + class RelatedHistory: - def __init__(self, name, model_name, object_id): + def __init__(self, name, app_name, model_name, object_id): """ :param name: Name of this instance :param model_name: Name of the related model (e.g. "user") :param object_id: ID of the related object """ self.name = "{} (id = {})".format(name, object_id) + self.app_name = app_name self.model_name = model_name self.object_id = object_id @@ -417,6 +426,10 @@ class History: self._last_version = version +############################ +# Revision history # +############################ + class VersionAction(HistoryEvent): def __init__(self, version): self.version = version @@ -496,6 +509,10 @@ class RevisionAction: return self.revision.get_comment() +############################ +# Class-specific history # +############################ + class UserHistoryEvent(HistoryEvent): def _repr(self, name, value): """ @@ -588,7 +605,7 @@ class UserHistory(History): super(UserHistory, self).__init__() self.event_type = UserHistoryEvent - def get(self, user_id): + def get(self, user_id, model): """ :param user_id: int, the id of the user to lookup :return: list or None, a list of UserHistoryEvent, in reverse chronological order @@ -633,7 +650,8 @@ class UserHistory(History): ) self.related = [RelatedHistory( m.field_dict["name"] or _("None"), - "machine", + "machines" + "Machine", m.field_dict["id"]) for m in self.related] self.related = list(dict.fromkeys(self.related)) @@ -716,7 +734,7 @@ class MachineHistory(History): super(MachineHistory, self).__init__() self.event_type = MachineHistoryEvent - def get(self, machine_id): + def get(self, machine_id, model): # Add as "related" histories the list of Interface objects # that were once assigned to this machine self.related = list( @@ -728,7 +746,8 @@ class MachineHistory(History): # Create RelatedHistory objects and remove duplicates self.related = [RelatedHistory( i.field_dict["mac_address"] or _("None"), - "interface", + "machines", + "Interface", i.field_dict["id"]) for i in self.related] self.related = list(dict.fromkeys(self.related)) @@ -782,10 +801,34 @@ class InterfaceHistory(History): super(InterfaceHistory, self).__init__() self.event_type = InterfaceHistoryEvent - def get(self, interface_id): + def get(self, interface_id, model): events = super(InterfaceHistory, self).get(interface_id, Interface) # Update name self.name = self._last_version.field_dict["mac_address"] return events + + +############################ +# History auto-detect # +############################ + +HISTORY_CLASS_MAPPING = { + User: UserHistory, + Machine: MachineHistory, + Interface: InterfaceHistory, + "default": History +} + + +def get_history_class(model): + """ + Find the mos appropriate History subclass to represent + the given model's history + :model: class + """ + try: + return HISTORY_CLASS_MAPPING[model]() + except KeyError: + return HISTORY_CLASS_MAPPING["default"]() diff --git a/logs/templates/logs/detailed_history.html b/logs/templates/logs/detailed_history.html index 7aaf67a0..8ffe5d68 100644 --- a/logs/templates/logs/detailed_history.html +++ b/logs/templates/logs/detailed_history.html @@ -82,7 +82,7 @@ with this program; if not, write to the Free Software Foundation, Inc., diff --git a/logs/templatetags/logs_extra.py b/logs/templatetags/logs_extra.py index 2e58cb67..c436c1fa 100644 --- a/logs/templatetags/logs_extra.py +++ b/logs/templatetags/logs_extra.py @@ -42,7 +42,7 @@ def is_facture(baseinvoice): @register.inclusion_tag("buttons/history.html") -def history_button(instance, text=False, detailed=False, html_class=True): +def history_button(instance, text=False, html_class=True): """Creates the correct history button for an instance. Args: @@ -57,6 +57,5 @@ def history_button(instance, text=False, detailed=False, html_class=True): "name": instance._meta.model_name, "id": instance.id, "text": text, - "detailed": detailed, "class": html_class, } diff --git a/logs/urls.py b/logs/urls.py index 914761bf..d70cc4a8 100644 --- a/logs/urls.py +++ b/logs/urls.py @@ -42,11 +42,6 @@ urlpatterns = [ views.history, name="history", ), - url( - r"(?P\w+)/(?P[0-9]+)$", - views.detailed_history, - name="detailed-history", - ), url(r"^stats_general/$", views.stats_general, name="stats-general"), url(r"^stats_models/$", views.stats_models, name="stats-models"), url(r"^stats_users/$", views.stats_users, name="stats-users"), diff --git a/logs/views.py b/logs/views.py index b71187aa..69102b31 100644 --- a/logs/views.py +++ b/logs/views.py @@ -37,7 +37,6 @@ nombre d'objets par models, nombre d'actions par user, etc """ from __future__ import unicode_literals -from itertools import chain from django.urls import reverse from django.shortcuts import render, redirect @@ -105,9 +104,7 @@ from .models import ( ActionsSearch, RevisionAction, MachineHistorySearch, - UserHistory, - MachineHistory, - InterfaceHistory + get_history_class ) from .forms import ( @@ -526,33 +523,24 @@ def stats_search_machine_history(request): return render(request, "logs/search_machine_history.html", {"history_form": history_form}) -def get_history_object(request, model, object_name, object_id, allow_deleted=False): +def get_history_object(request, model, object_name, object_id): """Get the objet of type model with the given object_id Handles permissions and DoesNotExist errors """ - is_deleted = False - try: object_name_id = object_name + "id" kwargs = {object_name_id: object_id} instance = model.get_instance(**kwargs) except model.DoesNotExist: - is_deleted = True instance = None - if is_deleted and not allow_deleted: - messages.error(request, _("Nonexistent entry.")) - return False, redirect( - reverse("users:profil", kwargs={"userid": str(request.user.id)}) - ) - - if is_deleted: - can_view = can_view_app("logs") + if instance is None: + authorized = can_view_app("logs") msg = None else: - can_view, msg, _permissions = instance.can_view(request.user) + authorized, msg, _permissions = instance.can_view(request.user) - if not can_view: + if not authorized: messages.error( request, msg or _("You don't have the right to access this menu.") ) @@ -563,61 +551,14 @@ def get_history_object(request, model, object_name, object_id, allow_deleted=Fal return True, instance -@login_required -def detailed_history(request, object_name, object_id): - """Render a detailed history for a model. - Permissions are handled by get_history_object. - """ - # Only handle objects for which a detailed view exists - if object_name == "user": - model = User - history = UserHistory() - elif object_name == "machine": - model = Machine - history = MachineHistory() - elif object_name == "interface": - model = Interface - history = InterfaceHistory() - else: - raise Http404(_("No model found.")) - - # Get instance and check permissions - can_view, instance = get_history_object(request, model, object_name, object_id, allow_deleted=True) - if not can_view: - return instance - - # Generate the pagination with the objects - max_result = GeneralOption.get_cached_value("pagination_number") - events = history.get(int(object_id)) - - # Events is None if object wasn't found - if events is None: - messages.error(request, _("Nonexistent entry.")) - return redirect( - reverse("users:profil", kwargs={"userid": str(request.user.id)}) - ) - - # Add the paginator in case there are many results - events = re2o_paginator(request, events, max_result) - - # Add a title in case the object was deleted - title = instance or "{} ({})".format(history.name, _("Deleted")) - - return render( - request, - "logs/detailed_history.html", - {"title": title, "events": events, "related_history": history.related}, - ) - - @login_required def history(request, application, object_name, object_id): """Render history for a model. The model is determined using the `HISTORY_BIND` dictionnary if none is found, raises a Http404. The view checks if the user is allowed to see the - history using the `can_view` method of the model. - Permissions are handled by get_history_object. + history using the `can_view` method of the model, or the generic + `can_view_app("logs")` for deleted objects (see `get_history_object`). Args: request: The request sent by the user. @@ -637,16 +578,29 @@ def history(request, application, object_name, object_id): except LookupError: raise Http404(_("No model found.")) - can_view, instance = get_history_object(request, model, object_name, object_id) + authorized, instance = get_history_object(request, model, object_name, object_id) if not can_view: return instance - pagination_number = GeneralOption.get_cached_value("pagination_number") - reversions = Version.objects.get_for_object(instance) - if hasattr(instance, "linked_objects"): - for related_object in chain(instance.linked_objects()): - reversions = reversions | Version.objects.get_for_object(related_object) - reversions = re2o_paginator(request, reversions, pagination_number) + history = get_history_class(model) + events = history.get(int(object_id), model) + + # Events is None if object wasn't found + if events is None: + messages.error(request, _("Nonexistent entry.")) + return redirect( + reverse("users:profil", kwargs={"userid": str(request.user.id)}) + ) + + # Generate the pagination with the objects + max_result = GeneralOption.get_cached_value("pagination_number") + events = re2o_paginator(request, events, max_result) + + # Add a default title in case the object was deleted + title = instance or "{} ({})".format(history.name, _("Deleted")) + return render( - request, "re2o/history.html", {"reversions": reversions, "object": instance} + request, + "logs/detailed_history.html", + {"title": title, "events": events, "related_history": history.related}, ) diff --git a/machines/templates/machines/aff_machines.html b/machines/templates/machines/aff_machines.html index 857d2a3a..77b65546 100644 --- a/machines/templates/machines/aff_machines.html +++ b/machines/templates/machines/aff_machines.html @@ -67,7 +67,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% trans "Create an interface" as tr_create_an_interface %} {% include 'buttons/add.html' with href='machines:new-interface' id=machine.id desc=tr_create_an_interface %} {% acl_end %} - {% history_button machine detailed=True %} + {% history_button machine %} {% can_delete machine %} {% include 'buttons/suppr.html' with href='machines:del-machine' id=machine.id %} {% acl_end %} @@ -161,7 +161,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% acl_end %} - {% history_button interface detailed=True %} + {% history_button interface %} {% can_delete interface %} {% include 'buttons/suppr.html' with href='machines:del-interface' id=interface.id %} {% acl_end %} diff --git a/templates/buttons/history.html b/templates/buttons/history.html index 2495dec8..71c2c71d 100644 --- a/templates/buttons/history.html +++ b/templates/buttons/history.html @@ -24,13 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% load i18n %} -{% if detailed %} - - {% if text %}{% trans "History" %}{% endif %} - -{% else %} {% if text %}{% trans "History" %}{% endif %} -{% endif %} diff --git a/users/templates/users/profil.html b/users/templates/users/profil.html index 4fa780a7..4fec3c18 100644 --- a/users/templates/users/profil.html +++ b/users/templates/users/profil.html @@ -176,7 +176,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% trans "Edit the groups" %} {% acl_end %} - {% history_button users text=True detailed=True %} + {% history_button users text=True %}
From 2b18d438a256cdb2dbd85d472a014bd52d61fcd7 Mon Sep 17 00:00:00 2001 From: Jean-Romain Garnier Date: Sat, 25 Apr 2020 12:40:10 +0200 Subject: [PATCH 2/7] Fix RelatedHistory init in detailed history --- logs/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/logs/models.py b/logs/models.py index 112d536f..3f42e6e1 100644 --- a/logs/models.py +++ b/logs/models.py @@ -650,8 +650,8 @@ class UserHistory(History): ) self.related = [RelatedHistory( m.field_dict["name"] or _("None"), - "machines" - "Machine", + "machines", + "machine", m.field_dict["id"]) for m in self.related] self.related = list(dict.fromkeys(self.related)) @@ -747,7 +747,7 @@ class MachineHistory(History): self.related = [RelatedHistory( i.field_dict["mac_address"] or _("None"), "machines", - "Interface", + "interface", i.field_dict["id"]) for i in self.related] self.related = list(dict.fromkeys(self.related)) From 37f87d6487faada5e2cf6f666151de784a47692e Mon Sep 17 00:00:00 2001 From: Jean-Romain Garnier Date: Sat, 25 Apr 2020 12:45:36 +0200 Subject: [PATCH 3/7] Remove detaild_history.html file --- logs/templates/logs/detailed_history.html | 94 ----------------------- logs/views.py | 2 +- re2o/templates/re2o/aff_history.html | 90 +++++++++++++++------- re2o/templates/re2o/history.html | 5 +- 4 files changed, 65 insertions(+), 126 deletions(-) delete mode 100644 logs/templates/logs/detailed_history.html diff --git a/logs/templates/logs/detailed_history.html b/logs/templates/logs/detailed_history.html deleted file mode 100644 index 8ffe5d68..00000000 --- a/logs/templates/logs/detailed_history.html +++ /dev/null @@ -1,94 +0,0 @@ -{% extends 'logs/sidebar.html' %} -{% comment %} -Re2o est un logiciel d'administration développé initiallement au rezometz. Il -se veut agnostique au réseau considéré, de manière à être installable en -quelques clics. - -Copyright © 2020 Jean-Romain Garnier - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -{% endcomment %} - -{% load bootstrap3 %} -{% load i18n %} -{% load logs_extra %} - -{% block title %}{% trans "History" %}{% endblock %} - -{% block content %} -

{% blocktrans %}History of {{ title }}{% endblocktrans %}

- -{% if events %} - - - - - - - - - - {% for event in events %} - - - - - - - {% endfor %} -
{% trans "Date" %}{% trans "Performed by" %}{% trans "Edited" %}{% trans "Comment" %}
{{ event.date }} - {% if event.performed_by %} - - {{ event.performed_by }} - - {% else %} - {% trans "Unknown" %} - {% endif %} - - {% for edit in event.edits %} - {% if edit.1 is None and edit.2 is None %} - {{ edit.0 }}
- {% elif edit.1 is None %} - {{ edit.0 }}: - {{ edit.2 }}
- {% else %} - {{ edit.0 }}: - {{ edit.1 }} - ➔ {{ edit.2 }}
- {% endif %} - {% endfor %} -
{{ event.comment }}
- {% include 'pagination.html' with list=events %} -{% else %} -

{% trans "No event" %}

-{% endif %} - -{% if related_history %} - -

{% blocktrans %}Related elements{% endblocktrans %}

- - -{% endif %} -
-
-
- -{% endblock %} diff --git a/logs/views.py b/logs/views.py index 69102b31..3f9fac5e 100644 --- a/logs/views.py +++ b/logs/views.py @@ -601,6 +601,6 @@ def history(request, application, object_name, object_id): return render( request, - "logs/detailed_history.html", + "re2o/history.html", {"title": title, "events": events, "related_history": history.related}, ) diff --git a/re2o/templates/re2o/aff_history.html b/re2o/templates/re2o/aff_history.html index 6256ff23..b8c8397a 100644 --- a/re2o/templates/re2o/aff_history.html +++ b/re2o/templates/re2o/aff_history.html @@ -6,6 +6,7 @@ quelques clics. Copyright © 2017 Gabriel Détraz Copyright © 2017 Lara Kermarec Copyright © 2017 Augustin Lemesle +Copyright © 2020 Jean-Romain Garnier This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,36 +24,67 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endcomment %} {% load i18n %} +{% load logs_extra %} - {% if reversions.paginator %} - - {% endif %} - - - +{% if events %} +
+ + + + + + + + + {% for event in events %} - - - + + + + - - {% for rev in reversions %} - - - - - - {% endfor %} -
{% trans "Date" %}{% trans "Performed by" %}{% trans "Edited" %}{% trans "Comment" %}
{% trans "Date" %}{% trans "Performed by" %}{% trans "Comment" %}{{ event.date }} + {% if event.performed_by %} + + {{ event.performed_by }} + + {% else %} + {% trans "Unknown" %} + {% endif %} + + {% for edit in event.edits %} + {% if edit.1 is None and edit.2 is None %} + {{ edit.0 }}
+ {% elif edit.1 is None %} + {{ edit.0 }}: + {{ edit.2 }}
+ {% else %} + {{ edit.0 }}: + {{ edit.1 }} + ➔ {{ edit.2 }}
+ {% endif %} + {% endfor %} +
{{ event.comment }}
{{ rev.revision.date_created }}{{ rev.revision.user }}{{ rev.revision.comment }}
+ {% endfor %} + + {% include 'pagination.html' with list=events %} +{% else %} +

{% trans "No event" %}

+{% endif %} + +{% if related_history %} + +

{% blocktrans %}Related elements{% endblocktrans %}

+ + +{% endif %} +
+
+
+ diff --git a/re2o/templates/re2o/history.html b/re2o/templates/re2o/history.html index 285fd62f..53ccd587 100644 --- a/re2o/templates/re2o/history.html +++ b/re2o/templates/re2o/history.html @@ -7,6 +7,7 @@ quelques clics. Copyright © 2017 Gabriel Détraz Copyright © 2017 Lara Kermarec Copyright © 2017 Augustin Lemesle +Copyright © 2020 Jean-Romain Garnier This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,8 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc., {% block title %}{% trans "History" %}{% endblock %} {% block content %} -

{% blocktrans %}History of {{ object }}{% endblocktrans %}

- {% include 're2o/aff_history.html' with reversions=reversions %} +

{% blocktrans %}History of {{ title }}{% endblocktrans %}

+ {% include 're2o/aff_history.html' with events=events related_history=related_history %}


From 13cb3f7990aa3258e1493604b8f57ba30113a238 Mon Sep 17 00:00:00 2001 From: Jean-Romain Garnier Date: Sat, 25 Apr 2020 12:59:01 +0200 Subject: [PATCH 4/7] Make RelatedHistory cleaner --- logs/models.py | 24 ++++++++---------------- re2o/templates/re2o/aff_history.html | 8 +++++++- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/logs/models.py b/logs/models.py index 3f42e6e1..e7d56afa 100644 --- a/logs/models.py +++ b/logs/models.py @@ -289,16 +289,17 @@ class MachineHistorySearch: ############################ class RelatedHistory: - def __init__(self, name, app_name, model_name, object_id): + def __init__(self, version): """ :param name: Name of this instance :param model_name: Name of the related model (e.g. "user") :param object_id: ID of the related object """ - self.name = "{} (id = {})".format(name, object_id) - self.app_name = app_name - self.model_name = model_name - self.object_id = object_id + self.version = version + self.app_name = version.content_type.app_label + self.model_name = version.content_type.model + self.object_id = version.object_id + self.name = version._object_cache or version.object_repr def __eq__(self, other): return ( @@ -646,13 +647,8 @@ class UserHistory(History): self.related = ( Version.objects.get_for_model(Machine) .filter(serialized_data__contains='"user": {}'.format(user_id)) - .order_by("-revision__date_created") ) - self.related = [RelatedHistory( - m.field_dict["name"] or _("None"), - "machines", - "machine", - m.field_dict["id"]) for m in self.related] + self.related = [RelatedHistory(v) for v in self.related] self.related = list(dict.fromkeys(self.related)) # Get all the versions for this user, with the oldest first @@ -744,11 +740,7 @@ class MachineHistory(History): ) # Create RelatedHistory objects and remove duplicates - self.related = [RelatedHistory( - i.field_dict["mac_address"] or _("None"), - "machines", - "interface", - i.field_dict["id"]) for i in self.related] + self.related = [RelatedHistory(v) for v in self.related] self.related = list(dict.fromkeys(self.related)) events = super(MachineHistory, self).get(machine_id, Machine) diff --git a/re2o/templates/re2o/aff_history.html b/re2o/templates/re2o/aff_history.html index b8c8397a..46eb82bc 100644 --- a/re2o/templates/re2o/aff_history.html +++ b/re2o/templates/re2o/aff_history.html @@ -78,7 +78,13 @@ with this program; if not, write to the Free Software Foundation, Inc., From de23ed7e03176d3a5d5855291933e36f7f6cfb0d Mon Sep 17 00:00:00 2001 From: Jean-Romain Garnier Date: Sat, 25 Apr 2020 11:09:22 +0000 Subject: [PATCH 5/7] Improve display of deleted objects in history --- logs/models.py | 17 ++++------------- re2o/templates/re2o/aff_history.html | 2 +- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/logs/models.py b/logs/models.py index e7d56afa..365424d9 100644 --- a/logs/models.py +++ b/logs/models.py @@ -299,7 +299,7 @@ class RelatedHistory: self.app_name = version.content_type.app_label self.model_name = version.content_type.model self.object_id = version.object_id - self.name = version._object_cache or version.object_repr + self.name = version.object_repr def __eq__(self, other): return ( @@ -390,6 +390,7 @@ class History: if self._last_version is None: return None + self.name = self._last_version.object_repr return self.events[::-1] def _compute_diff(self, v1, v2, ignoring=[]): @@ -743,12 +744,7 @@ class MachineHistory(History): self.related = [RelatedHistory(v) for v in self.related] self.related = list(dict.fromkeys(self.related)) - events = super(MachineHistory, self).get(machine_id, Machine) - - # Update name - self.name = self._last_version.field_dict["name"] - - return events + return super(MachineHistory, self).get(machine_id, Machine) class InterfaceHistoryEvent(HistoryEvent): @@ -794,12 +790,7 @@ class InterfaceHistory(History): self.event_type = InterfaceHistoryEvent def get(self, interface_id, model): - events = super(InterfaceHistory, self).get(interface_id, Interface) - - # Update name - self.name = self._last_version.field_dict["mac_address"] - - return events + return super(InterfaceHistory, self).get(interface_id, Interface) ############################ diff --git a/re2o/templates/re2o/aff_history.html b/re2o/templates/re2o/aff_history.html index 46eb82bc..a52ecc38 100644 --- a/re2o/templates/re2o/aff_history.html +++ b/re2o/templates/re2o/aff_history.html @@ -79,7 +79,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% for related in related_history %}
  • {% if related.object_id %} - + {{ related.name }} {% else %} From c3e246c64d64e5d60309bbb6374a043e24959a14 Mon Sep 17 00:00:00 2001 From: Jean-Romain Garnier Date: Sat, 25 Apr 2020 11:22:39 +0000 Subject: [PATCH 6/7] Make related history more extensive for users and machines --- logs/models.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/logs/models.py b/logs/models.py index 365424d9..56bf962a 100644 --- a/logs/models.py +++ b/logs/models.py @@ -301,6 +301,9 @@ class RelatedHistory: self.object_id = version.object_id self.name = version.object_repr + if self.model_name: + self.name = "{}: {}".format(self.model_name.title(), self.name) + def __eq__(self, other): return ( self.model_name == other.model_name @@ -643,11 +646,14 @@ class UserHistory(History): if obj is None: return None - # Add in "related" elements the list of Machine objects + # Add in "related" elements the list of objects # that were once owned by this user + query = Q(serialized_data__contains='"user": {}'.format(user_id)) + query &= ~Q(serialized_data__contains='"model": "users.user"') self.related = ( - Version.objects.get_for_model(Machine) - .filter(serialized_data__contains='"user": {}'.format(user_id)) + Version.objects.all() + .filter(query) + .order_by("content_type__model") ) self.related = [RelatedHistory(v) for v in self.related] self.related = list(dict.fromkeys(self.related)) @@ -732,12 +738,13 @@ class MachineHistory(History): self.event_type = MachineHistoryEvent def get(self, machine_id, model): - # Add as "related" histories the list of Interface objects - # that were once assigned to this machine - self.related = list( + query = Q(serialized_data__contains='"machine": {}'.format(machine_id)) + query &= ~Q(serialized_data__contains='"model": "machines.machine"') + + self.related = ( Version.objects.get_for_model(Interface) - .filter(serialized_data__contains='"machine": {}'.format(machine_id)) - .order_by("-revision__date_created") + .filter(query) + .order_by("content_type__model") ) # Create RelatedHistory objects and remove duplicates From 568dd3b41573ab3e82d4fda245676fb3b5df0aa9 Mon Sep 17 00:00:00 2001 From: Jean-Romain Garnier Date: Sat, 25 Apr 2020 11:26:18 +0000 Subject: [PATCH 7/7] Remove useless query in detailed history --- logs/models.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/logs/models.py b/logs/models.py index 56bf962a..a9aaa7aa 100644 --- a/logs/models.py +++ b/logs/models.py @@ -648,11 +648,9 @@ class UserHistory(History): # Add in "related" elements the list of objects # that were once owned by this user - query = Q(serialized_data__contains='"user": {}'.format(user_id)) - query &= ~Q(serialized_data__contains='"model": "users.user"') self.related = ( Version.objects.all() - .filter(query) + .filter(serialized_data__contains='"user": {}'.format(user_id)) .order_by("content_type__model") ) self.related = [RelatedHistory(v) for v in self.related] @@ -738,12 +736,9 @@ class MachineHistory(History): self.event_type = MachineHistoryEvent def get(self, machine_id, model): - query = Q(serialized_data__contains='"machine": {}'.format(machine_id)) - query &= ~Q(serialized_data__contains='"model": "machines.machine"') - self.related = ( Version.objects.get_for_model(Interface) - .filter(query) + .filter(serialized_data__contains='"machine": {}'.format(machine_id)) .order_by("content_type__model") )