浏览代码

Updated basket analytics signal - wasn't working previously

- Also refactored the calculate scores management command
master
David Winterbottom 14 年前
父节点
当前提交
2478c36c8f

+ 7
- 29
oscar/apps/analytics/management/commands/calculate_scores.py 查看文件

@@ -1,42 +1,20 @@
1 1
 import logging
2
-import sys
3
-from optparse import make_option
4 2
 
5
-from django.core.management.base import BaseCommand, CommandError
6
-from django.db import connection, transaction
3
+from django.core.management.base import BaseCommand
7 4
 
8
-from oscar.apps.analytics.models import ProductRecord
9
-from oscar.apps.catalogue.models import Item
5
+from oscar.core.loading import import_module
6
+import_module('analytics.utils', ['ScoreCalculator'], locals())
10 7
 
11 8
 
12 9
 class Command(BaseCommand):
13 10
     
14
-    help = 'For creating product catalogues based on a CSV file'
11
+    help = 'Calculate product scores based on analytics data'
15 12
     
16 13
     def handle(self, *args, **options):
17 14
         
18
-        logger = self._get_logger()
19
-        cursor = connection.cursor()
20
-        
21
-        logger.info("Calculating product scores")
22
-        sql = '''UPDATE `%s` 
23
-                 SET score = (num_views + 3*num_basket_additions + 5*num_purchases) / 9''' % ProductRecord._meta.db_table
24
-        cursor.execute(sql)
25
-        
26
-        logger.info("Updating product table")
27
-        sql = '''UPDATE `%s` product, `%s` analytics
28
-                 SET product.score = analytics.score
29
-                 WHERE product.id = analytics.product_id''' % (Product._meta.db_table, ProductRecord._meta.db_table)
30
-        cursor.execute(sql)
31
-        
32
-        transaction.commit_unless_managed()
33
-        
34
-    def _get_logger(self):
35
-        logger = logging.getLogger('oscar.apps.score_calculation')
36
-        stream = logging.StreamHandler(self.stdout)
37
-        logger.addHandler(stream)
38
-        logger.setLevel(logging.DEBUG)
39
-        return logger
15
+        logger = logging.getLogger(__name__)
16
+        calculator = ScoreCalculator(logger)
17
+        calculator.run()
40 18
 
41 19
         
42 20
         

+ 44
- 0
oscar/apps/analytics/utils.py 查看文件

@@ -0,0 +1,44 @@
1
+from django.db import connection, transaction
2
+
3
+from oscar.core.loading import import_module
4
+import_module('analytics.models', ['ProductRecord'], locals())
5
+import_module('catalogue.models', ['Product'], locals())
6
+
7
+
8
+class ScoreCalculator(object):
9
+    
10
+    # Map of field name to weight
11
+    weights = {'num_views': 1,
12
+               'num_basket_additions': 3,
13
+               'num_purchases': 5}
14
+    
15
+    def __init__(self, logger):
16
+        self.logger = logger
17
+        self.cursor = connection.cursor()
18
+    
19
+    def run(self):
20
+        self.calculate_scores()
21
+        self.update_product_models()
22
+        
23
+    def calculate_scores(self):
24
+        self.logger.info("Calculating product scores")
25
+        
26
+        # Build the "SET ..." part of the SQL statement
27
+        weighted_sum = " + ".join(["%s*`%s`" % (weight, field) for field, weight in self.weights.items()])
28
+        
29
+        ctx = {'table': ProductRecord._meta.db_table,
30
+               'weighted_total': weighted_sum,
31
+               'total_weight': sum(self.weights.values())}
32
+        sql = '''UPDATE `%(table)s` 
33
+                 SET score = (%(weighted_total)s) / %(total_weight)s''' % ctx
34
+        self.logger.debug(sql)         
35
+        self.cursor.execute(sql)
36
+        transaction.commit_unless_managed()
37
+        
38
+    def update_product_models(self):
39
+        self.logger.info("Updating product records")
40
+        sql = '''UPDATE `%s` product, `%s` analytics
41
+                 SET product.score = analytics.score
42
+                 WHERE product.id = analytics.product_id''' % (Product._meta.db_table, ProductRecord._meta.db_table)
43
+        self.cursor.execute(sql)
44
+        transaction.commit_unless_managed()

+ 6
- 0
oscar/apps/basket/views.py 查看文件

@@ -9,6 +9,7 @@ from django.utils.translation import ugettext_lazy as _
9 9
 from extra_views import ModelFormSetView
10 10
 from oscar.apps.basket.forms import BasketLineForm, AddToBasketForm, \
11 11
     BasketVoucherForm, SavedLineForm
12
+from oscar.apps.basket.signals import basket_addition
12 13
 
13 14
 
14 15
 class BasketView(ModelFormSetView):
@@ -70,6 +71,7 @@ class BasketAddView(FormView):
70 71
     """
71 72
     form_class = AddToBasketForm
72 73
     product_model = get_model('catalogue', 'product')
74
+    add_signal = basket_addition
73 75
     
74 76
     def get(self, request, *args, **kwargs):
75 77
         return HttpResponseRedirect(reverse('basket:summary'))
@@ -96,6 +98,10 @@ class BasketAddView(FormView):
96 98
         messages.info(self.request, _("'%(title)s' (quantity %(quantity)d) has been added to your basket" %
97 99
                 {'title': form.instance.get_title(), 
98 100
                  'quantity': form.cleaned_data['quantity']}))
101
+        
102
+        # Send signal for basket addition
103
+        self.add_signal.send(sender=self, product=form.instance, user=self.request.user)
104
+        
99 105
         return super(BasketAddView, self).form_valid(form)
100 106
     
101 107
     def form_invalid(self, form):

+ 3
- 3
oscar/apps/catalogue/views.py 查看文件

@@ -21,8 +21,8 @@ class ProductDetailView(DetailView):
21 21
         return self._product
22 22
     
23 23
     def get(self, request, **kwargs):
24
-        u"""
25
-        Ensures that the correct URL is used
24
+        """
25
+        Ensure that the correct URL is used
26 26
         """
27 27
         product = self.get_object()
28 28
         correct_path = product.get_absolute_url() 
@@ -36,7 +36,7 @@ class ProductDetailView(DetailView):
36 36
 
37 37
     def get_template_names(self):
38 38
         """
39
-        Returns a list of possible templates.
39
+        Return a list of possible templates.
40 40
         
41 41
         We try 2 options before defaulting to catalogue/detail.html:
42 42
         1). detail-for-upc-<upc>.html

正在加载...
取消
保存