Преглед на файлове

Improved basket usage.

* Less DB queries
* Added basic tests
master
David Winterbottom преди 13 години
родител
ревизия
369fa8e828
променени са 4 файла, в които са добавени 41 реда и са изтрити 27 реда
  1. 7
    3
      oscar/apps/basket/abstract_models.py
  2. 8
    8
      oscar/apps/basket/middleware.py
  3. 1
    1
      oscar/templates/oscar/partials/nav_alternate.html
  4. 25
    15
      tests/unit/basket_tests.py

+ 7
- 3
oscar/apps/basket/abstract_models.py Целия файл

63
         This is important for offers as they alter the line models and you don't
63
         This is important for offers as they alter the line models and you don't
64
         want to reload them from the DB.
64
         want to reload them from the DB.
65
         """
65
         """
66
+        if self.id is None:
67
+            return []
66
         if self._lines is None:
68
         if self._lines is None:
67
             self._lines = self.lines.all()
69
             self._lines = self.lines.all()
68
         return self._lines
70
         return self._lines
237
 
239
 
238
     @property
240
     @property
239
     def is_empty(self):
241
     def is_empty(self):
240
-        """Return bool based on basket having 0 lines"""
241
-        return self.num_lines == 0
242
+        """
243
+        Test if this basket is empty
244
+        """
245
+        return self.id is None or self.num_lines == 0
242
 
246
 
243
     @property
247
     @property
244
     def total_excl_tax(self):
248
     def total_excl_tax(self):
319
     @property
323
     @property
320
     def num_lines(self):
324
     def num_lines(self):
321
         """Return number of lines"""
325
         """Return number of lines"""
322
-        return self.all_lines().count()
326
+        return len(self.all_lines())
323
 
327
 
324
     @property
328
     @property
325
     def num_items(self):
329
     def num_items(self):

+ 8
- 8
oscar/apps/basket/middleware.py Целия файл

13
 class BasketMiddleware(object):
13
 class BasketMiddleware(object):
14
 
14
 
15
     def process_request(self, request):
15
     def process_request(self, request):
16
-        self.cookies_to_delete = []
16
+        request.cookies_to_delete = []
17
         basket = self.get_basket(request)
17
         basket = self.get_basket(request)
18
         self.apply_offers_to_basket(request, basket)
18
         self.apply_offers_to_basket(request, basket)
19
         request.basket = basket
19
         request.basket = basket
23
         cookie_basket = self.get_cookie_basket(settings.OSCAR_BASKET_COOKIE_OPEN,
23
         cookie_basket = self.get_cookie_basket(settings.OSCAR_BASKET_COOKIE_OPEN,
24
                                                request, manager)
24
                                                request, manager)
25
 
25
 
26
-        if request.user.is_authenticated():
26
+        if hasattr(request, 'user') and request.user.is_authenticated():
27
             # Signed-in user: if they have a cookie basket too, it means
27
             # Signed-in user: if they have a cookie basket too, it means
28
             # that they have just signed in and we need to merge their cookie
28
             # that they have just signed in and we need to merge their cookie
29
             # basket into their user basket, then delete the cookie
29
             # basket into their user basket, then delete the cookie
31
                 basket, _ = manager.get_or_create(owner=request.user)
31
                 basket, _ = manager.get_or_create(owner=request.user)
32
             except Basket.MultipleObjectsReturned:
32
             except Basket.MultipleObjectsReturned:
33
                 # Not sure quite how we end up here with multiple baskets
33
                 # Not sure quite how we end up here with multiple baskets
34
-                # We merge any  them and create a fresh one
34
+                # We merge them and create a fresh one
35
                 old_baskets = list(manager.filter(owner=request.user))
35
                 old_baskets = list(manager.filter(owner=request.user))
36
                 basket = old_baskets[0]
36
                 basket = old_baskets[0]
37
                 for other_basket in old_baskets[1:]:
37
                 for other_basket in old_baskets[1:]:
39
 
39
 
40
             if cookie_basket:
40
             if cookie_basket:
41
                 self.merge_baskets(basket, cookie_basket)
41
                 self.merge_baskets(basket, cookie_basket)
42
-                self.cookies_to_delete.append(settings.OSCAR_BASKET_COOKIE_OPEN)
42
+                request.cookies_to_delete.append(settings.OSCAR_BASKET_COOKIE_OPEN)
43
         elif cookie_basket:
43
         elif cookie_basket:
44
             # Anonymous user with a basket tied to the cookie
44
             # Anonymous user with a basket tied to the cookie
45
             basket = cookie_basket
45
             basket = cookie_basket
59
 
59
 
60
     def process_response(self, request, response):
60
     def process_response(self, request, response):
61
         # Delete any surplus cookies
61
         # Delete any surplus cookies
62
-        if hasattr(self, 'cookies_to_delete'):
63
-            for cookie_key in self.cookies_to_delete:
62
+        if hasattr(request, 'cookies_to_delete'):
63
+            for cookie_key in request.cookies_to_delete:
64
                 response.delete_cookie(cookie_key)
64
                 response.delete_cookie(cookie_key)
65
 
65
 
66
         # If a basket has had products added to it, but the user is anonymous
66
         # If a basket has had products added to it, but the user is anonymous
100
                     basket = Basket.objects.get(pk=basket_id, owner=None,
100
                     basket = Basket.objects.get(pk=basket_id, owner=None,
101
                                                 status=OPEN)
101
                                                 status=OPEN)
102
                 except Basket.DoesNotExist:
102
                 except Basket.DoesNotExist:
103
-                    self.cookies_to_delete.append(cookie_key)
103
+                    request.cookies_to_delete.append(cookie_key)
104
             else:
104
             else:
105
-                self.cookies_to_delete.append(cookie_key)
105
+                request.cookies_to_delete.append(cookie_key)
106
         return basket
106
         return basket
107
 
107
 
108
     def apply_offers_to_basket(self, request, basket):
108
     def apply_offers_to_basket(self, request, basket):

+ 1
- 1
oscar/templates/oscar/partials/nav_alternate.html Целия файл

11
             </a>
11
             </a>
12
             <a class="btn btn-navbar app-ico ico_shop_bag btn-cart hidden" href="{% url checkout:index %}">
12
             <a class="btn btn-navbar app-ico ico_shop_bag btn-cart hidden" href="{% url checkout:index %}">
13
 				<strong>{% trans "Basket" %}
13
 				<strong>{% trans "Basket" %}
14
-                {% if request.basket.lines.count %}
14
+                {% if not request.basket.is_empty %}
15
 				{% trans "Total:" %} {{ basket.total_incl_tax|currency }}
15
 				{% trans "Total:" %} {{ basket.total_incl_tax|currency }}
16
                 {% endif %}
16
                 {% endif %}
17
                 </strong>
17
                 </strong>

+ 25
- 15
tests/unit/basket_tests.py Целия файл

1
 import datetime
1
 import datetime
2
 
2
 
3
 from django.test import TestCase
3
 from django.test import TestCase
4
+from django.test.client import RequestFactory
4
 
5
 
5
-from oscar.apps.basket.models import Basket, Line
6
+from oscar.apps.basket.models import Basket
7
+from oscar.apps.basket.middleware import BasketMiddleware
6
 from oscar.test.helpers import create_product
8
 from oscar.test.helpers import create_product
7
 from oscar.apps.basket.reports import (
9
 from oscar.apps.basket.reports import (
8
     OpenBasketReportGenerator, SubmittedBasketReportGenerator)
10
     OpenBasketReportGenerator, SubmittedBasketReportGenerator)
9
 
11
 
10
 
12
 
11
-class BasketModelTest(TestCase):
13
+class TestBasketModel(TestCase):
12
 
14
 
13
     def setUp(self):
15
     def setUp(self):
14
         self.basket = Basket.objects.create()
16
         self.basket = Basket.objects.create()
15
-        self.dummy_product = create_product()
17
+        self.product = create_product()
16
 
18
 
17
-    def test_empty_baskets_have_zero_lines(self):
18
-        self.assertTrue(Basket().num_lines == 0)
19
+    def test_an_empty_basket_has_zero_lines(self):
20
+        self.assertEqual(0, self.basket.num_lines)
19
 
21
 
20
     def test_new_baskets_are_empty(self):
22
     def test_new_baskets_are_empty(self):
21
-        self.assertTrue(Basket().is_empty)
23
+        self.assertTrue(self.basket.is_empty)
22
 
24
 
23
-    def test_basket_have_with_one_line(self):
24
-        Line.objects.create(basket=self.basket, product=self.dummy_product)
25
-        self.assertTrue(self.basket.num_lines == 1)
26
-
27
-    def test_add_product_creates_line(self):
28
-        self.basket.add_product(self.dummy_product)
29
-        self.assertTrue(self.basket.num_lines == 1)
25
+    def test_adding_product_creates_line(self):
26
+        self.basket.add_product(self.product)
27
+        self.assertEqual(1, self.basket.num_lines)
30
 
28
 
31
     def test_adding_multiproduct_line_returns_correct_number_of_items(self):
29
     def test_adding_multiproduct_line_returns_correct_number_of_items(self):
32
-        self.basket.add_product(self.dummy_product, 10)
30
+        self.basket.add_product(self.product, 10)
33
         self.assertEqual(self.basket.num_items, 10)
31
         self.assertEqual(self.basket.num_items, 10)
32
+        self.assertEqual(self.basket.num_lines, 1)
33
+
34
+
35
+class TestBasketMiddleware(TestCase):
36
+
37
+    def setUp(self):
38
+        self.middleware = BasketMiddleware()
39
+
40
+    def test_basket_is_attached_to_request(self):
41
+        req = RequestFactory().get('/')
42
+        self.middleware.process_request(req)
43
+        self.assertTrue(hasattr(req, 'basket'))
34
 
44
 
35
 
45
 
36
-class BasketReportTests(TestCase):
46
+class TestBasketReports(TestCase):
37
 
47
 
38
     def test_open_report_doesnt_error(self):
48
     def test_open_report_doesnt_error(self):
39
         data = {
49
         data = {

Loading…
Отказ
Запис