From: Guillaume Pellerin Date: Mon, 22 Apr 2013 15:21:44 +0000 (+0200) Subject: fix query to speedup filters X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=809b5c1dfc075ef4a61ebf28b15d29da28d049af;p=django-postman.git fix query to speedup filters --- diff --git a/postman/models.py b/postman/models.py index 9da2e28..9bef0d8 100644 --- a/postman/models.py +++ b/postman/models.py @@ -8,6 +8,7 @@ except ImportError: from postman.future_1_5 import get_user_model from django.core.exceptions import ValidationError from django.db import models +from django.db.models.query import QuerySet try: from django.utils.text import Truncator # Django 1.4 except ImportError: @@ -19,6 +20,7 @@ except ImportError: from datetime import datetime now = datetime.now +from postman.query import PostmanQuery from postman.urls import OPTION_MESSAGES from postman.utils import email_visitor, notify_user @@ -41,8 +43,8 @@ ORDER_BY_FIELDS = { } ORDER_BY_MAPPER = {'sender': 'f', 'recipient': 't', 'subject': 's', 'date': 'd'} # for templatetags usage -dbms = settings.DATABASES['default']['ENGINE'].rsplit('.', 1)[-1] -QUOTE_CHAR = '`' if dbms == 'mysql' else '"' +# dbms = settings.DATABASES['default']['ENGINE'].rsplit('.', 1)[-1] +# QUOTE_CHAR = '`' if dbms == 'mysql' else '"' def get_order_by(query_dict): @@ -80,22 +82,22 @@ def get_user_representation(user): pass return unicode(user) # default value, or in case of empty attribute or exception - +# import logging +# logging.getLogger('django.db.backends').setLevel(logging.DEBUG) class MessageManager(models.Manager): """The manager for Message.""" - @property - def _last_in_thread(self): - """Return the latest message id for each conversation.""" - return self.filter(thread__isnull=False).values('thread').annotate(models.Max('pk'))\ - .values_list('pk__max', flat=True).order_by() + # @property + # def _last_in_thread(self): + # """Return the latest message id for each conversation.""" + # return self.filter(thread__isnull=False).values('thread').annotate(models.Max('pk'))\ + # .values_list('pk__max', flat=True).order_by() def _folder(self, related, filters, option=None, order_by=None): """Base code, in common to the folders.""" + qs = self.all() if option == OPTION_MESSAGES else QuerySet(self.model, PostmanQuery(self.model), using=self._db) if related: - qs = self.select_related(*related) - else: - qs = self.all() + qs = qs.select_related(*related) if order_by: qs = qs.order_by(order_by) if isinstance(filters, (list, tuple)): @@ -110,12 +112,25 @@ class MessageManager(models.Manager): # should not be necessary. Otherwise add: # .extra(select={'count': 'SELECT 1'}) else: - return qs.filter( - models.Q(id__in=self._last_in_thread.filter(lookups)) | models.Q(lookups, thread__isnull=True) - ).extra(select={'count': QUOTE_CHAR.join([ - 'SELECT COUNT(*) FROM ', 'postman_message', ' T' - ' WHERE T.', 'thread_id', ' = ', 'postman_message', '.', 'thread_id', ' ' - ])}) + qs = qs.extra(select={'count': '{0}.count'.format(qs.query.pm_alias_prefix)}) + qs.query.pm_set_extra(table=( + self.filter(lookups, thread_id__isnull=True).extra(select={'count': 0})\ + .values_list('id', 'count').order_by(), + self.filter(lookups, thread_id__isnull=False).values('thread').annotate(id=models.Max('pk'), count=models.Count('pk'))\ + .values_list('id', 'count').order_by(), + )) + return qs + # from rqs import PostmanRawQuery, PostmanRawQuerySet + # raw_query = 'select *, 12 as count from postman_message' + # query = PostmanRawQuery(sql=raw_query, using=Message.objects.db) + # rqs = PostmanRawQuerySet(raw_query=raw_query, model=Message, query=query) + # return rqs + # return qs.filter( + # models.Q(id__in=self._last_in_thread.filter(lookups)) | models.Q(lookups, thread__isnull=True) + # ).extra(select={'count': QUOTE_CHAR.join([ + # 'SELECT COUNT(*) FROM ', 'postman_message', ' T' + # ' WHERE T.', 'thread_id', ' = ', 'postman_message', '.', 'thread_id', ' ' + # ])}) # For single message, 'count' is returned as 0. Should be acceptable if known. # If not, replace "COUNT(*)" by "1+COUNT(*)" and add: # ' AND T."id" <> T."thread_id"'