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.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. Applicator = get_class('offer.utils', 'Applicator')
  6. Basket = get_model('basket', 'basket')
  7. class BasketMiddleware(object):
  8. def process_request(self, request):
  9. request.cookies_to_delete = []
  10. basket = self.get_basket(request)
  11. self.apply_offers_to_basket(request, basket)
  12. request.basket = basket
  13. def get_basket(self, request):
  14. manager = Basket.open
  15. cookie_basket = self.get_cookie_basket(
  16. settings.OSCAR_BASKET_COOKIE_OPEN, request, manager)
  17. if hasattr(request, 'user') and request.user.is_authenticated():
  18. # Signed-in user: if they have a cookie basket too, it means
  19. # that they have just signed in and we need to merge their cookie
  20. # basket into their user basket, then delete the cookie
  21. try:
  22. basket, _ = manager.get_or_create(owner=request.user)
  23. except Basket.MultipleObjectsReturned:
  24. # Not sure quite how we end up here with multiple baskets
  25. # We merge them and create a fresh one
  26. old_baskets = list(manager.filter(owner=request.user))
  27. basket = old_baskets[0]
  28. for other_basket in old_baskets[1:]:
  29. self.merge_baskets(basket, other_basket)
  30. if cookie_basket:
  31. self.merge_baskets(basket, cookie_basket)
  32. request.cookies_to_delete.append(
  33. 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(request, 'cookies_to_delete'):
  51. for cookie_key in request.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" % (
  59. request.basket.id, self.get_basket_hash(request.basket.id))
  60. response.set_cookie(settings.OSCAR_BASKET_COOKIE_OPEN,
  61. cookie,
  62. max_age=settings.OSCAR_BASKET_COOKIE_LIFETIME,
  63. httponly=True)
  64. return response
  65. def process_template_response(self, request, response):
  66. if hasattr(response, 'context_data'):
  67. if response.context_data is None:
  68. response.context_data = {}
  69. response.context_data['basket'] = request.basket
  70. return response
  71. def get_cookie_basket(self, cookie_key, request, manager):
  72. """
  73. Looks for a basket which is referenced by a cookie.
  74. If a cookie key is found with no matching basket, then we add
  75. it to the list to be deleted.
  76. """
  77. basket = None
  78. if cookie_key in request.COOKIES:
  79. parts = request.COOKIES[cookie_key].split("_")
  80. if len(parts) != 2:
  81. return basket
  82. basket_id, basket_hash = parts
  83. if basket_hash == self.get_basket_hash(basket_id):
  84. try:
  85. basket = Basket.objects.get(pk=basket_id, owner=None,
  86. status=Basket.OPEN)
  87. except Basket.DoesNotExist:
  88. request.cookies_to_delete.append(cookie_key)
  89. else:
  90. request.cookies_to_delete.append(cookie_key)
  91. return basket
  92. def apply_offers_to_basket(self, request, basket):
  93. if not basket.is_empty:
  94. Applicator().apply(request, basket)
  95. def get_basket_hash(self, basket_id):
  96. return str(zlib.crc32(str(basket_id) + settings.SECRET_KEY))