From c9c9eea37ec81db82897ca113eba5b8a5d375957 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 16 Jan 2013 22:54:12 +0100 Subject: [PATCH] Perfomance of the *identities* page has been improved. see #315 --- modoboa/admin/models.py | 50 ++++++++++++------- .../templates/admin/identities_table.html | 21 ++++++++ modoboa/admin/templatetags/admin_extras.py | 11 ++-- modoboa/admin/views.py | 29 +++++++---- 4 files changed, 79 insertions(+), 32 deletions(-) create mode 100644 modoboa/admin/templates/admin/identities_table.html diff --git a/modoboa/admin/models.py b/modoboa/admin/models.py index 713dfd6fb..d3ef96535 100644 --- a/modoboa/admin/models.py +++ b/modoboa/admin/models.py @@ -186,7 +186,7 @@ class User(DUser): @property def has_mailbox(self): - return len(self.mailbox_set.all()) != 0 + return self.mailbox_set.count() != 0 @property def fullname(self): @@ -212,6 +212,10 @@ class User(DUser): return self.groups.all()[0].name except IndexError: return "?" + + @property + def enabled(self): + return self.is_active def belongs_to_group(self, name): """Simple shortcut to check if this user is a member of a @@ -250,10 +254,18 @@ class User(DUser): :return: a queryset """ from modoboa.lib.permissions import get_content_type - + from itertools import chain + userct = get_content_type(self) + ids = self.objectaccess_set.filter(content_type=userct) \ + .values_list('object_id', flat=True) + result = User.objects.select_related().filter(pk__in=ids) + alct = get_content_type(Alias) - return self.objectaccess_set.filter(content_type__in=[userct, alct]) + ids = self.objectaccess_set.filter(content_type=alct) \ + .values_list('object_id', flat=True) + return chain(result, Alias.objects.select_related().filter(pk__in=ids)) + def get_domains(self): """Return the domains belonging to this user @@ -498,15 +510,15 @@ class Domain(DatesAware): @property def domainalias_count(self): - return len(self.domainalias_set.all()) + return self.domainalias_set.count() @property def mailbox_count(self): - return len(self.mailbox_set.all()) + return self.mailbox_set.count() @property def mbalias_count(self): - return len(self.alias_set.all()) + return self.alias_set.count() @property def admins(self): @@ -536,13 +548,13 @@ class Domain(DatesAware): def delete(self, keepdir=False): from modoboa.lib.permissions import ungrant_access_to_object, ungrant_access_to_objects - if len(self.domainalias_set.all()): + if self.domainalias_set.count(): events.raiseEvent("DomainAliasDeleted", self.domainalias_set.all()) ungrant_access_to_objects(self.domainalias_set.all()) - if len(self.mailbox_set.all()): + if self.mailbox_set.count(): events.raiseEvent("DeleteMailbox", self.mailbox_set.all()) ungrant_access_to_objects(self.mailbox_set.all()) - if len(self.alias_set.all()): + if self.alias_set.count(): events.raiseEvent("MailboxAliasDelete", self.alias_set.all()) ungrant_access_to_objects(self.alias_set.all()) events.raiseEvent("DeleteDomain", self) @@ -670,7 +682,7 @@ class Mailbox(DatesAware): @property def alias_count(self): - return len(self.alias_set.all()) + return self.alias_set.count() def create_dir(self): if self.mbtype == "mbox": @@ -776,7 +788,7 @@ class Mailbox(DatesAware): raise AdminError(_("Account '%s' already exists" % user.username)) self.user = user - if len(user.groups.all()) == 0: + if user.groups.count() == 0: user.groups.add(Group.objects.get(name="SimpleUsers")) user.save() @@ -829,7 +841,7 @@ def mailbox_deleted_handler(sender, **kwargs): ungrant_access_to_object(mb) for alias in mb.alias_set.all(): alias.mboxes.remove(mb) - if len(alias.mboxes.all()) == 0: + if alias.mboxes.count() == 0: alias.delete() class Alias(DatesAware): @@ -863,16 +875,17 @@ class Alias(DatesAware): @property def name_or_rcpt(self): - rcpts = self.get_recipients() - if not len(rcpts): + rcpts_count = self.get_recipients_count() + if not rcpts_count: return "---" - if len(rcpts) > 1: + rcpts = self.get_recipients() + if rcpts_count > 1: return "%s, ..." % rcpts[0] return rcpts[0] @property def tags(self): - cpt = len(self.get_recipients()) + cpt = self.get_recipients_count() if cpt > 1: label = _("distribution list") elif self.extmboxes != "": @@ -912,6 +925,9 @@ class Alias(DatesAware): result += self.extmboxes.split(',') return result + def get_recipients_count(self): + return self.mboxes.count() + len(self.extmboxes.split(',')) + def ui_disabled(self, user): if user.is_superuser: return False @@ -951,7 +967,7 @@ class Alias(DatesAware): self.save(int_rcpts, ext_rcpts) def to_csv(self, csvwriter): - cpt = len(self.get_recipients()) + cpt = self.get_recipients_count() if cpt > 1: altype = "dlist" elif self.extmboxes != "": diff --git a/modoboa/admin/templates/admin/identities_table.html b/modoboa/admin/templates/admin/identities_table.html new file mode 100644 index 000000000..8703095b9 --- /dev/null +++ b/modoboa/admin/templates/admin/identities_table.html @@ -0,0 +1,21 @@ +{% load i18n admin_extras %} + + + + + + + + + + + {% for ident in identities %} + + + + + + + {% endfor %} + +
{% trans "Name" %}{% trans "Fullname/Recipient" %}{% trans "Tags" %}{% trans "Actions" %}
{{ ident.identity }}{{ ident.name_or_rcpt }}{{ ident.tags|safe }}{% identity_actions user ident %}
diff --git a/modoboa/admin/templatetags/admin_extras.py b/modoboa/admin/templatetags/admin_extras.py index 0797e5d84..b0210b28c 100644 --- a/modoboa/admin/templatetags/admin_extras.py +++ b/modoboa/admin/templatetags/admin_extras.py @@ -152,8 +152,9 @@ def domain_actions(user, domid): return "---" @register.simple_tag -def identity_actions(user, iid): - name, objid = iid.split(':') +def identity_actions(user, ident): + name = ident.__class__.__name__ + objid = ident.id if name == "User": actions = [ {"name" : "delaccount", @@ -162,16 +163,14 @@ def identity_actions(user, iid): "title" : _("Delete this account")}, ] else: - from modoboa.admin.models import Alias - alias = Alias.objects.get(pk=objid) - if len(alias.get_recipients()) >= 2: + if ident.get_recipients_count() >= 2: actions = [ {"name" : "deldlist", "url" : reverse(admin.views.deldlist) + "?selection=%s" % objid, "img" : "icon-trash", "title" : _("Delete this distribution list")}, ] - elif alias.extmboxes != "": + elif ident.extmboxes != "": actions = [ {"name" : "delforward", "url" : reverse(admin.views.delforward) + "?selection=%s" % objid, diff --git a/modoboa/admin/views.py b/modoboa/admin/views.py index 9489731c3..8243f66a9 100644 --- a/modoboa/admin/views.py +++ b/modoboa/admin/views.py @@ -10,14 +10,14 @@ from django.db import transaction, IntegrityError import cStringIO import csv -from lib import render_listing +from lib import * from forms import * from models import * from modoboa.admin.tables import * from modoboa.lib import events, parameters from modoboa.lib.exceptions import * from modoboa.lib.webutils \ - import _render, ajax_response, ajax_simple_response + import _render, ajax_response, ajax_simple_response, _render_to_string from modoboa.lib.emailutils import split_mailbox from modoboa.lib.models import Parameter from modoboa.lib.permissions import * @@ -315,13 +315,24 @@ def _identities(request): else: q = Q(address__contains=squery) objects += [al for al in Alias.objects.filter(Q(pk__in=alids) & q)] - else: - objects = [] - for oa in idents_list: - if oa.content_object: - objects.append(oa.content_object) - objects = sorted(objects, key=lambda o: o.identity) - return render_listing(request, "identities", objects=objects, squery=squery) + + objects = sorted(idents_list, key=lambda o: o.identity) + + paginator = Paginator(objects, int(parameters.get_admin("ITEMS_PER_PAGE"))) + pagenum = int(request.GET.get("page", "1")) + try: + page = paginator.page(pagenum) + except (EmptyPage, PageNotAnInteger): + page = paginator.page(paginator.num_pages) + + return ajax_simple_response({ + "table" : _render_to_string(request, "admin/identities_table.html", { + "identities" : page.object_list, + "tableid" : "objects_table" + }), + "page" : page.number, + "paginbar" : pagination_bar(page) + }) @login_required @user_passes_test(lambda u: u.has_perm("auth.add_user") or u.has_perm("admin.add_alias"))