You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

middleware.py 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import zlib
  2. from django.conf import settings
  3. from django.db.models import get_model
  4. from oscar.core.loading import get_class
  5. from oscar.apps.basket.abstract_models import OPEN
  6. Applicator = get_class('offer.utils', 'Applicator')
  7. Basket = get_model('basket', 'basket')
  8. class BasketMiddleware(object):
  9. def process_request(self, request):
  10. self.cookies_to_delete = []
  11. basket = self.get_basket(request)
  12. self.apply_offers_to_basket(request, basket)
  13. request.basket = basket
  14. def get_basket(self, request):
  15. manager = Basket.open
  16. cookie_basket = self.get_cookie_basket(settings.OSCAR_BASKET_COOKIE_OPEN,
  17. request, manager)
  18. if request.user.is_authenticated():
  19. # Signed-in user: if they have a cookie basket too, it means
  20. # that they have just signed in and we need to merge their cookie
  21. # basket into their user basket, then delete the cookie
  22. try:
  23. basket, _ = manager.get_or_create(owner=request.user)
  24. except Basket.MultipleObjectsReturned:
  25. # Not sure quite how we end up here with multiple baskets
  26. # We merge any them and create a fresh one
  27. old_baskets = list(manager.filter(owner=request.user))
  28. basket = old_baskets[0]
  29. for other_basket in old_baskets[1:]:
  30. self.merge_baskets(basket, other_basket)
  31. if cookie_basket:
  32. self.merge_baskets(basket, cookie_basket)
  33. self.cookies_to_delete.append(settings.OSCAR_BASKET_COOKIE_OPEN)
  34. elif cookie_basket:
  35. # Anonymous user with a basket tied to the cookie
  36. basket = cookie_basket
  37. else:
  38. # Anonymous user with no basket - we don't save the basket until
  39. # we need to.
  40. basket = Basket()
  41. return basket
  42. def merge_baskets(self, master, slave):
  43. """
  44. Merge one basket into another.
  45. This is its own method to allow it to be overridden
  46. """
  47. master.merge(slave, add_quantities=False)
  48. def process_response(self, request, response):
  49. # Delete any surplus cookies
  50. if hasattr(self, 'cookies_to_delete'):
  51. for cookie_key in self.cookies_to_delete:
  52. response.delete_cookie(cookie_key)
  53. # If a basket has had products added to it, but the user is anonymous
  54. # then we need to assign it to a cookie
  55. if hasattr(request, 'basket') and request.basket.id > 0 \
  56. and not request.user.is_authenticated() \
  57. and settings.OSCAR_BASKET_COOKIE_OPEN not in request.COOKIES:
  58. cookie = "%s_%s" % (request.basket.id, self.get_basket_hash(request.basket.id))
  59. response.set_cookie(settings.OSCAR_BASKET_COOKIE_OPEN,
  60. cookie,
  61. max_age=settings.OSCAR_BASKET_COOKIE_LIFETIME,
  62. httponly=True)
  63. return response
  64. def process_template_response(self, request, response):
  65. if hasattr(response, 'context_data'):
  66. if response.context_data is None:
  67. response.context_data = {}
  68. response.context_data['basket'] = request.basket
  69. return response
  70. def get_cookie_basket(self, cookie_key, request, manager):
  71. """
  72. Looks for a basket which is referenced by a cookie.
  73. If a cookie key is found with no matching basket, then we add
  74. it to the list to be deleted.
  75. """
  76. basket = None
  77. if cookie_key in request.COOKIES:
  78. parts = request.COOKIES[cookie_key].split("_")
  79. if len(parts) != 2:
  80. return basket
  81. basket_id, basket_hash = parts
  82. if basket_hash == self.get_basket_hash(basket_id):
  83. try:
  84. basket = Basket.objects.get(pk=basket_id, owner=None,
  85. status=OPEN)
  86. except Basket.DoesNotExist:
  87. self.cookies_to_delete.append(cookie_key)
  88. else:
  89. self.cookies_to_delete.append(cookie_key)
  90. return basket
  91. def apply_offers_to_basket(self, request, basket):
  92. if not basket.is_empty:
  93. Applicator().apply(request, basket)
  94. def get_basket_hash(self, basket_id):
  95. return str(zlib.crc32(str(basket_id)+settings.SECRET_KEY))