New single entry random dataset helper
[ckanext-ga-report.git] / ckanext / ga_report / helpers.py
blob:a/ckanext/ga_report/helpers.py -> blob:b/ckanext/ga_report/helpers.py
--- a/ckanext/ga_report/helpers.py
+++ b/ckanext/ga_report/helpers.py
@@ -1,7 +1,9 @@
 import logging
 import operator
+
 import ckan.lib.base as base
 import ckan.model as model
+from ckan.logic import get_action
 
 from ckanext.ga_report.ga_model import GA_Url, GA_Publisher
 from ckanext.ga_report.controller import _get_publishers
@@ -28,28 +30,54 @@
     return base.render_snippet('ga_report/ga_popular_datasets.html', **ctx)
 
 def single_popular_dataset(top=20):
+    '''Returns a random dataset from the most popular ones.
+
+    :param top: the number of top datasets to select from
+    '''
     import random
 
-    datasets = {}
-    rand = random.randrange(0, top)
-    entry = model.Session.query(GA_Url).\
-        filter(GA_Url.url.like('/dataset/%')).\
-        order_by('ga_url.pageviews::int desc')[rand]
-
+    top_datasets = model.Session.query(GA_Url).\
+                   filter(GA_Url.url.like('/dataset/%')).\
+                   order_by('ga_url.pageviews::int desc')
+    num_top_datasets = top_datasets.count()
 
     dataset = None
-    while not dataset:
-        dataset = model.Package.get(entry.url[len('/dataset/'):])
-        if dataset and not dataset.state == 'active':
-            dataset = None
-        else:
-            publisher = model.Group.get(entry.department_id)
+    if num_top_datasets:
+        count = 0
+        while not dataset:
+            rand = random.randrange(0, min(top, num_top_datasets))
+            ga_url = top_datasets[rand]
+            dataset = model.Package.get(ga_url.url[len('/dataset/'):])
+            if dataset and not dataset.state == 'active':
+                dataset = None
+            # When testing, it is possible that top datasets are not available
+            # so only go round this loop a few times before falling back on
+            # a random dataset.
+            count += 1
+            if count > 10:
+                break
+    if not dataset:
+        # fallback
+        dataset = model.Session.query(model.Package)\
+                  .filter_by(state='active').first()
+        if not dataset:
+            return None
+    dataset_dict = get_action('package_show')({'model': model,
+                                               'session': model.Session,
+                                               'validate': False},
+                                              {'id':dataset.id})
+    return dataset_dict
 
-    ctx = {
-        'dataset': dataset,
-        'publisher': publisher
-    }
-    return base.render_snippet('ga_report/ga_popular_single.html', **ctx)
+def single_popular_dataset_html(top=20):
+    dataset_dict = single_popular_dataset(top)
+    groups = package.get('groups', [])
+    publishers = [ g for g in groups if g.get('type') == 'publisher' ]
+    publisher = publishers[0] if publishers else {'name':'', 'title': ''}
+    context = {
+        'dataset': dataset_dict,
+        'publisher': publisher_dict
+        }
+    return base.render_snippet('ga_report/ga_popular_single.html', **context)
 
 
 def most_popular_datasets(publisher, count=20):
@@ -61,7 +89,7 @@
     results = _datasets_for_publisher(publisher, count)
 
     ctx = {
-        'dataset_count': len(datasets),
+        'dataset_count': len(results),
         'datasets': results,
 
         'publisher': publisher
@@ -78,10 +106,14 @@
     for entry in entries:
         if len(datasets) < count:
             p = model.Package.get(entry.url[len('/dataset/'):])
+            if not p:
+                _log.warning("Could not find Package for {url}".format(url=entry.url))
+                continue
+
             if not p in datasets:
                 datasets[p] = {'views':0, 'visits': 0}
             datasets[p]['views'] = datasets[p]['views'] + int(entry.pageviews)
-            datasets[p]['visits'] = datasets[p]['visits'] + int(entry.visitors)
+            datasets[p]['visits'] = datasets[p]['visits'] + int(entry.visits)
 
     results = []
     for k, v in datasets.iteritems():