From 5a8e75112f7cc59358e85699caa6836b2f3a4451 Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Sun, 28 Feb 2016 00:41:03 +0000 Subject: [PATCH] Added a custom manager for groupped logs --- src/documents/managers.py | 70 +++++++++++++++++++++++++++++++++++++++ src/documents/models.py | 4 +++ 2 files changed, 74 insertions(+) create mode 100644 src/documents/managers.py diff --git a/src/documents/managers.py b/src/documents/managers.py new file mode 100644 index 000000000..d7e7225eb --- /dev/null +++ b/src/documents/managers.py @@ -0,0 +1,70 @@ +from django.conf import settings + +from django.db import models +from django.db.models.aggregates import Max + + +class Concat(models.Aggregate): + """ + Theoretically, this should work in Sqlite, PostgreSQL, and MySQL, but I've + only ever tested it in Sqlite. + """ + + ENGINE_SQLITE = 1 + ENGINE_POSTGRESQL = 2 + ENGINE_MYSQL = 3 + ENGINES = { + "django.db.backends.sqlite3": ENGINE_SQLITE, + "django.db.backends.postgresql_psycopg2": ENGINE_POSTGRESQL, + "django.db.backends.postgresql": ENGINE_POSTGRESQL, + "django.db.backends.mysql": ENGINE_MYSQL + } + + def __init__(self, expression, separator="\n", **extra): + + self.engine = self._get_engine() + self.function = self._get_function() + self.template = self._get_template(separator) + + models.Aggregate.__init__( + self, + expression, + output_field=models.CharField(), + **extra + ) + + def _get_engine(self): + engine = settings.DATABASES["default"]["ENGINE"] + try: + return self.ENGINES[engine] + except KeyError: + raise NotImplementedError( + "There's currently no support for {} when it comes to group " + "concatenation in Paperless".format(engine) + ) + + def _get_function(self): + if self.engine == self.ENGINE_POSTGRESQL: + return "STRING_AGG" + return "GROUP_CONCAT" + + def _get_template(self, separator): + if self.engine == self.ENGINE_MYSQL: + return "%(function)s(%(expressions)s, SEPARATOR '{}')".format( + separator) + return "%(function)s(%(expressions)s, '{}')".format(separator) + + +class LogQuerySet(models.query.QuerySet): + + def by_group(self): + return self.values("group").annotate( + time=Max("modified"), + messages=Concat("message"), + ).order_by("-time") + + +class LogManager(models.Manager): + + def get_queryset(self): + return LogQuerySet(self.model, using=self._db) diff --git a/src/documents/models.py b/src/documents/models.py index 91dd458ea..e5556534a 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -8,6 +8,8 @@ from django.db import models from django.template.defaultfilters import slugify from django.utils import timezone +from .managers import LogManager + class SluggedModel(models.Model): @@ -214,6 +216,8 @@ class Log(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) + objects = LogManager() + class Meta(object): ordering = ("-modified",)