Projet

Général

Profil

0002-custom-attributes-prefetching-29531.patch

Emmanuel Cazenave, 15 janvier 2019 14:59

Télécharger (3,86 ko)

Voir les différences:

Subject: [PATCH 2/2] custom attributes prefetching (#29531)

 src/authentic2/manager/user_views.py | 21 +++++++++++++--------
 tests/test_user_manager.py           |  2 +-
 2 files changed, 14 insertions(+), 9 deletions(-)
src/authentic2/manager/user_views.py
11 11
from django.template import loader
12 12
from django.core.urlresolvers import reverse
13 13
from django.contrib.auth import get_user_model
14
from django.contrib.contenttypes.models import ContentType
14 15
from django.contrib import messages
15 16
from django.http import HttpResponseRedirect, QueryDict
16 17
from django.views.generic.detail import SingleObjectMixin
......
20 21
import tablib
21 22

  
22 23
from authentic2.constants import SWITCH_USER_SESSION_KEY
23
from authentic2.models import Attribute, PasswordReset
24
from authentic2.models import Attribute, AttributeValue, PasswordReset
24 25
from authentic2.utils import switch_user, send_password_reset_mail, redirect, send_email_change_email
25 26
from authentic2.a2_rbac.utils import get_default_ou
26 27
from authentic2 import hooks
......
323 324
    resource_class = UserResource
324 325
    export_prefix = 'users-'
325 326

  
326
    def get_queryset(self):
327
        '''Prefetch attribute values.'''
328
        qs = super(UsersExportView, self).get_queryset()
329
        return qs.prefetch_related('attribute_values', 'attribute_values__attribute')
330

  
331 327
    @property
332 328
    def csv(self):
333 329
        return self._dataset.export('csv')
......
338 334
        attributes = [attr.name for attr in Attribute.objects.all()]
339 335
        headers = fields + tuple(['attribute_%s' % attr for attr in attributes])
340 336

  
337
        at_mapping = {a.id: a for a in Attribute.objects.all()}
338
        avs = AttributeValue.objects.filter(
339
            content_type=ContentType.objects.get_for_model(get_user_model())).values()
340
        user_attrs = collections.defaultdict(dict)
341
        for av in avs:
342
            user_attrs[av['object_id']][at_mapping[av['attribute_id']].name] = av['content']
343

  
341 344
        def iso(rec):
345
            if rec is None or rec == {}:
346
                return ''
342 347
            if hasattr(rec, 'strftime'):
343 348
                if isinstance(rec, datetime.datetime):
344 349
                    _format = "%Y-%m-%d %H:%M:%S"
......
356 361
                    value = getattr(user, field)
357 362
                record.append(value)
358 363

  
359
            attr_d = user.attributes.values
364
            attr_d = user_attrs[user.pk]
360 365
            for attr in attributes:
361
                record.append(attr_d.get(attr, ''))
366
                record.append(attr_d.get(attr))
362 367

  
363 368
            return map(iso, record)
364 369

  
tests/test_user_manager.py
124 124
    user_count = User.objects.count()
125 125
    # queries should be batched to keep prefetching working without
126 126
    # overspending memory for the queryset cache, 4 queries by batches
127
    num_queries = 9 + 4 * (user_count / DEFAULT_BATCH_SIZE + bool(user_count % DEFAULT_BATCH_SIZE))
127
    num_queries = 4 + 4 * (user_count / DEFAULT_BATCH_SIZE + bool(user_count % DEFAULT_BATCH_SIZE))
128 128
    with django_assert_num_queries(num_queries):
129 129
         response = response.click('CSV')
130 130
    table = list(csv.reader(response.content.splitlines()))
131
-