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 3.4KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import zlib
  2. from django.conf import settings
  3. from django.core.exceptions import SuspiciousOperation
  4. from oscar.core.loading import import_module
  5. import_module('basket.models', ['Basket'], locals())
  6. import_module('offer.utils', ['Applicator'], locals())
  7. class BasketMiddleware(object):
  8. cookies_to_delete = []
  9. def process_request(self, request):
  10. manager = Basket.open
  11. cookie_basket = self.get_cookie_basket(settings.OSCAR_BASKET_COOKIE_OPEN,
  12. request, manager)
  13. if request.user.is_authenticated():
  14. # Signed-in user: if they have a cookie basket too, it means
  15. # that they have just signed in and we need to merge their cookie
  16. # basket into their user basket, then delete the cookie
  17. basket, _ = Basket.open.get_or_create(owner=request.user)
  18. if cookie_basket:
  19. basket.merge(cookie_basket)
  20. self.cookies_to_delete.append(settings.OSCAR_BASKET_COOKIE_OPEN)
  21. elif cookie_basket:
  22. # Anonymous user with a basket tied to the cookie
  23. basket = cookie_basket
  24. else:
  25. # Anonymous user with no basket - we don't save the basket until
  26. # we need to.
  27. basket = Basket()
  28. # Assign basket object to request
  29. self.apply_offers_to_basket(request, basket)
  30. request.basket = basket
  31. def process_response(self, request, response):
  32. # Delete any surplus cookies
  33. for cookie_key in self.cookies_to_delete:
  34. response.delete_cookie(cookie_key)
  35. # If a basket has had products added to it, but the user is anonymous
  36. # then we need to assign it to a cookie
  37. if hasattr(request, 'basket') and request.basket.id > 0 and not request.user.is_authenticated():
  38. cookie = "%s_%s" % (request.basket.id, self.get_basket_hash(request.basket.id))
  39. response.set_cookie(settings.OSCAR_BASKET_COOKIE_OPEN,
  40. cookie,
  41. max_age=settings.OSCAR_BASKET_COOKIE_LIFETIME,
  42. httponly=True)
  43. return response
  44. def process_template_response(self, request, response):
  45. if response.context_data is None:
  46. response.context_data = {}
  47. response.context_data['basket'] = request.basket
  48. return response
  49. def get_cookie_basket(self, cookie_key, request, manager):
  50. """
  51. Looks for a basket which is referenced by a cookie.
  52. If a cookie key is found with no matching basket, then we add
  53. it to the list to be deleted.
  54. """
  55. basket = None
  56. if cookie_key in request.COOKIES:
  57. basket_id, basket_hash = request.COOKIES[cookie_key].split("_")
  58. if basket_hash == self.get_basket_hash(basket_id):
  59. try:
  60. basket = Basket.objects.get(pk=basket_id, owner=None)
  61. except Basket.DoesNotExist:
  62. self.cookies_to_delete.append(cookie_key)
  63. else:
  64. self.cookies_to_delete.append(cookie_key)
  65. return basket
  66. def apply_offers_to_basket(self, request, basket):
  67. if not basket.is_empty:
  68. Applicator().apply(request, basket)
  69. def get_basket_hash(self, basket_id):
  70. return str(zlib.crc32(str(id)+settings.SECRET_KEY))