[FIX] website_membership: perf, pagination

This fixes :
 * pagination only on /members and sometimes with bad page count,
 * free members could not be searched (were always all displayed),
 * all elements are displayed even if there is a pagination,
 * for members without country, errors happened in some use case,
 * when too much locations were on a map (>2000) it failed,
 * numbers of members by countries was not displayed for guest.

And also as performance improvemnts:
 * only query all partners when the map is enabled (customize > left
   world map),
 * limit partners put on the map to 2000 (even then it's a lot for
   google maps),
 * don't browse all membership_line to get res_partner but use a query.

opw-634653
This commit is contained in:
Nicolas Lempereur 2015-05-07 13:51:25 +02:00
parent 68599dcd43
commit 5804246e0f
3 changed files with 76 additions and 11 deletions

View File

@ -27,7 +27,7 @@ class WebsiteMembership(http.Controller):
'/members/association/<membership_id>/country/<country_name>-<int:country_id>/page/<int:page>',
'/members/association/<membership_id>/country/<int:country_id>/page/<int:page>',
], type='http', auth="public", website=True)
def members(self, membership_id=None, country_name=None, country_id=0, page=0, **post):
def members(self, membership_id=None, country_name=None, country_id=0, page=1, **post):
cr, uid, context = request.cr, request.uid, request.context
product_obj = request.registry['product.product']
country_obj = request.registry['res.country']
@ -56,7 +56,7 @@ class WebsiteMembership(http.Controller):
membership_line_ids = []
country_domain = ('free_member', '=', True)
countries = partner_obj.read_group(
cr, uid, [country_domain, ("website_published", "=", True)], ["id", "country_id"],
cr, SUPERUSER_ID, [country_domain, ("website_published", "=", True)], ["id", "country_id"],
groupby="country_id", orderby="country_id", context=request.context)
countries_total = sum(country_dict['country_id_count'] for country_dict in countries)
@ -64,11 +64,12 @@ class WebsiteMembership(http.Controller):
if country_id:
line_domain.append(('partner.country_id', '=', country_id))
current_country = country_obj.read(cr, uid, country_id, ['id', 'name'], context)
if not any(x['country_id'][0] == country_id for x in countries):
if not any(x['country_id'][0] == country_id for x in countries if x['country_id']):
countries.append({
'country_id_count': 0,
'country_id': (country_id, current_country["name"])
})
countries = filter(lambda d:d['country_id'], countries)
countries.sort(key=lambda d: d['country_id'][1])
countries.insert(0, {
@ -82,15 +83,32 @@ class WebsiteMembership(http.Controller):
# make sure we don't access to lines with unpublished membershipts
line_domain.append(('membership_id', 'in', membership_ids))
# displayed membership lines
limit = self._references_per_page
offset = limit * (page - 1)
count_members = 0
membership_line_ids = []
# displayed non-free membership lines
if membership_id != 'free':
membership_line_ids = membership_line_obj.search(cr, SUPERUSER_ID, line_domain, context=context)
count_members = membership_line_obj.search_count(cr, SUPERUSER_ID, line_domain, context=context)
if offset <= count_members:
membership_line_ids = tuple(membership_line_obj.search(cr, SUPERUSER_ID, line_domain, offset, limit, context=context))
membership_lines = membership_line_obj.browse(cr, uid, membership_line_ids, context=context)
# TODO: Following line can be deleted in master. Kept for retrocompatibility.
membership_lines = sorted(membership_lines, key=lambda x: x.membership_id.website_sequence)
partner_ids = [m.partner.id for m in membership_lines]
free_partner_ids = partner_obj.search(cr, SUPERUSER_ID, [('free_member', '=', True), ('website_published', '=', True)], context=context)
google_map_partner_ids = ",".join(map(str, partner_ids))
page_partner_ids = set(m.partner.id for m in membership_lines)
google_map_partner_ids = []
if request.env.ref('website_membership.opt_index_google_map').customize_show:
membership_lines_ids = membership_line_obj.search(cr, uid, line_domain, context=context)
google_map_partner_ids = membership_line_obj.get_published_companies(cr, uid, membership_line_ids, limit=2000, context=context)
search_domain = [('free_member', '=', True), ('website_published', '=', True)]
if post_name:
search_domain += ['|', ('name', 'ilike', post_name), ('website_description', 'ilike', post_name)]
if country_id:
search_domain += [('country_id', '=', country_id)]
free_partner_ids = partner_obj.search(cr, SUPERUSER_ID, search_domain, context=context)
memberships_data = []
for membership_record in memberships:
memberships_data.append({'id': membership_record.id, 'name': membership_record.name})
@ -100,12 +118,23 @@ class WebsiteMembership(http.Controller):
if free_partner_ids:
memberships_data.append({'id': 'free', 'name': _('Free Members')})
if not membership_id or membership_id == 'free':
memberships_partner_ids['free'] = free_partner_ids
if count_members < offset + limit:
free_start = max(offset - count_members, 0)
free_end = max(offset + limit - count_members, 0)
memberships_partner_ids['free'] = free_partner_ids[free_start:free_end]
page_partner_ids |= set(memberships_partner_ids['free'])
google_map_partner_ids += free_partner_ids[:2000-len(google_map_partner_ids)]
count_members += len(free_partner_ids)
partners = dict((p.id, p) for p in partner_obj.browse(request.cr, SUPERUSER_ID, list(set(partner_ids + free_partner_ids)), request.context))
google_map_partner_ids = ",".join(map(str, google_map_partner_ids))
partners = { p.id: p for p in partner_obj.browse(request.cr, SUPERUSER_ID, list(page_partner_ids), request.context)}
base_url = '/members%s%s' % ('/association/%s' % membership_id if membership_id else '',
'/country/%s' % country_id if country_id else '')
# request pager for lines
pager = request.website.pager(url="/members", total=len(membership_line_ids), page=page, step=self._references_per_page, scope=7, url_args=post)
pager = request.website.pager(url=base_url, total=count_members, page=page, step=limit, scope=7, url_args=post)
values = {
'partners': partners,

View File

@ -1 +1,2 @@
import product
import membership

View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import osv, fields
class membership_membership_line(osv.Model):
_inherit = 'membership.membership_line'
def get_published_companies(self, cr, uid, ids, limit=None, context=None):
if not ids:
return []
limit_clause = '' if limit is None else ' LIMIT %d' % limit
cr.execute('SELECT DISTINCT p.id \
FROM res_partner p INNER JOIN membership_membership_line m \
ON p.id = m.partner \
WHERE website_published AND is_company AND m.id IN %s ' + limit_clause, (tuple(ids),))
return [partner_id[0] for partner_id in cr.fetchall()]