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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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. # Assign user onto basket to prevent further SQL queries when
  31. # basket.owner is accessed.
  32. basket.owner = request.user
  33. if cookie_basket:
  34. self.merge_baskets(basket, cookie_basket)
  35. request.cookies_to_delete.append(
  36. settings.OSCAR_BASKET_COOKIE_OPEN)
  37. elif cookie_basket:
  38. # Anonymous user with a basket tied to the cookie
  39. basket = cookie_basket
  40. else:
  41. # Anonymous user with no basket - we don't save the basket until
  42. # we need to.
  43. basket = Basket()
  44. return basket
  45. def merge_baskets(self, master, slave):
  46. """
  47. Merge one basket into another.
  48. This is its own method to allow it to be overridden
  49. """
  50. master.merge(slave, add_quantities=False)
  51. def process_response(self, request, response):
  52. # Delete any surplus cookies
  53. if hasattr(request, 'cookies_to_delete'):
  54. for cookie_key in request.cookies_to_delete:
  55. response.delete_cookie(cookie_key)
  56. # If a basket has had products added to it, but the user is anonymous
  57. # then we need to assign it to a cookie
  58. if (hasattr(request, 'basket') and request.basket.id > 0
  59. and not request.user.is_authenticated()
  60. and settings.OSCAR_BASKET_COOKIE_OPEN not in request.COOKIES):
  61. cookie = "%s_%s" % (
  62. request.basket.id, self.get_basket_hash(request.basket.id))
  63. response.set_cookie(settings.OSCAR_BASKET_COOKIE_OPEN,
  64. cookie,
  65. max_age=settings.OSCAR_BASKET_COOKIE_LIFETIME,
  66. httponly=True)
  67. return response
  68. def process_template_response(self, request, response):
  69. if hasattr(response, 'context_data'):
  70. if response.context_data is None:
  71. response.context_data = {}
  72. response.context_data['basket'] = request.basket
  73. return response
  74. def get_cookie_basket(self, cookie_key, request, manager):
  75. """
  76. Looks for a basket which is referenced by a cookie.
  77. If a cookie key is found with no matching basket, then we add
  78. it to the list to be deleted.
  79. """
  80. basket = None
  81. if cookie_key in request.COOKIES:
  82. parts = request.COOKIES[cookie_key].split("_")
  83. if len(parts) != 2:
  84. return basket
  85. basket_id, basket_hash = parts
  86. if basket_hash == self.get_basket_hash(basket_id):
  87. try:
  88. basket = Basket.objects.get(pk=basket_id, owner=None,
  89. status=Basket.OPEN)
  90. except Basket.DoesNotExist:
  91. request.cookies_to_delete.append(cookie_key)
  92. else:
  93. request.cookies_to_delete.append(cookie_key)
  94. return basket
  95. def apply_offers_to_basket(self, request, basket):
  96. if not basket.is_empty:
  97. Applicator().apply(request, basket)
  98. def get_basket_hash(self, basket_id):
  99. return str(zlib.crc32(str(basket_id) + settings.SECRET_KEY))