Permalink
Browse files

add skills and engagement_level to csv export

  • Loading branch information...
rmarianski committed Nov 7, 2012
1 parent dc63349 commit 11c0c487fe5f8927a6587b54b4b047267745f389
Showing with 20 additions and 6 deletions.
  1. +20 −6 search/views.py
View
@@ -952,25 +952,39 @@ def safe_encode(value):
return str(value)
-def user_to_csv_row(user, fields):
+def user_to_csv_row(user, fields, field_fns):
row = []
for field in fields:
- value = getattr(user, field, '') or ''
- if callable(value):
- value = value()
+ field_fn = field_fns.get(field, None)
+ if field_fn is not None:
+ value = field_fn(user)
+ else:
+ value = getattr(user, field, '') or ''
+ if callable(value):
+ value = value()
value = safe_encode(value)
row.append(value)
return row
+def corefield_value(field_name):
+ def get_corefield(user):
+ values = [f.value for f in user.fields.all() if f.name == field_name]
@ejucovy

ejucovy Nov 12, 2012

Contributor

This function is inefficient -- I believe that user.fields.all() will trigger a new DB query each time it's called (Django doesn't cache these things, at least I don't think it does) so that's a new query each time corefield_value's inner function is called.

But even worse than that, it's doing this for each user in the list; the context here is a CSV export of multiple users, so for a list with 100 users, that's like 200 extra DB queries.

Instead of this function, we should use stuff like queryset.extra(select={"skills": "selectvaluefromcore_userfieldwherecore_userfield.name= "skills" andcore_userfield.parent_id=core_user.id}) -- that way these attributes will land on each CoreUser object as a result of the initial SELECT * FROM core_user query. See views.py L656 for an example of where we're already doing this in the underlying _search function (which is probably where this should happen too)

(Or alternatively we could do a single select on all core_userfields that match our current list of users, and shuffle them onto the right users and the right attributes in Python code: CoreUserfield.objects.filter(parent__id__in=list_of_core_user_ids); presumably as the number of distinct fields we collect grows, that'll become the more efficient choice.)

+ return ','.join(values)
+ return get_corefield
+
+
@authorize("search_export")
@allow_http("GET")
@rendered_with("search_csv.html")
def search_csv(request):
user_fields = ['first_name', 'last_name', 'email',
'address1', 'address2', 'city', 'state', 'region',
'postal', 'zip', 'country',
- 'source', 'subscription_status', 'phone', 'campus']
+ 'source', 'subscription_status', 'phone', 'campus',
+ 'skills', 'engagement_level']
+ field_fns = dict(skills=corefield_value('skills'),
+ engagement_level=corefield_value('engagement_level'))
fields = request.GET.getlist('fields')
if not fields:
keyvals = []
@@ -986,7 +1000,7 @@ def search_csv(request):
writer.writerow(fields)
users = _search(request)['users']
for user in users:
- row = user_to_csv_row(user, fields)
+ row = user_to_csv_row(user, fields, field_fns)
writer.writerow(row)
response = HttpResponse(buffer.getvalue())
response['Content-Type'] = 'text/csv'

0 comments on commit 11c0c48

Please sign in to comment.