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.

core_views.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. from django.http import HttpResponse, Http404, HttpResponseRedirect, HttpResponseBadRequest
  2. from django.contrib import messages
  3. from django.core.urlresolvers import reverse
  4. from oscar.core.loading import import_module
  5. import_module('checkout.calculators', ['OrderTotalCalculator'], locals())
  6. import_module('order.models', ['Order', 'ShippingAddress'], locals())
  7. import_module('checkout.utils', ['ProgressChecker', 'CheckoutSessionData'], locals())
  8. import_module('address.models', ['UserAddress'], locals())
  9. def prev_steps_must_be_complete(view_fn):
  10. u"""
  11. Decorator fn for checking that previous steps of the checkout
  12. are complete.
  13. The completed steps (identified by URL-names) are stored in the session.
  14. If this fails, then we redirect to the next uncompleted step.
  15. """
  16. def _view_wrapper(self, request, *args, **kwargs):
  17. checker = ProgressChecker()
  18. if not checker.are_previous_steps_complete(request):
  19. messages.error(request, "You must complete this step of the checkout first")
  20. url_name = checker.get_next_step(request)
  21. return HttpResponseRedirect(reverse(url_name))
  22. return view_fn(self, request, *args, **kwargs)
  23. return _view_wrapper
  24. def basket_required(view_fn):
  25. def _view_wrapper(self, request, *args, **kwargs):
  26. if request.basket.is_empty:
  27. messages.error(request, "You must add some products to your basket before checking out")
  28. return HttpResponseRedirect(reverse('oscar-basket'))
  29. return view_fn(self, request, *args, **kwargs)
  30. return _view_wrapper
  31. def mark_step_as_complete(request):
  32. u"""
  33. Convenience function for marking a checkout page
  34. as complete.
  35. """
  36. ProgressChecker().step_complete(request)
  37. def get_next_step(request):
  38. return ProgressChecker().get_next_step(request)
  39. class CheckoutView(object):
  40. u"""
  41. Top-level superclass for all checkout view classes
  42. """
  43. def __init__(self, template_file=None):
  44. if template_file:
  45. self.template_file = template_file
  46. @basket_required
  47. @prev_steps_must_be_complete
  48. def __call__(self, request):
  49. u"""
  50. We forward request handling to the appropriate method
  51. based on the HTTP method.
  52. """
  53. # Set up the instance variables that are needed to place an order
  54. self.request = request
  55. self.co_data = CheckoutSessionData(request)
  56. self.basket = request.basket
  57. # Set up template context that is available to every view
  58. method = self.co_data.shipping_method()
  59. if method:
  60. method.set_basket(self.basket)
  61. self.context = {'basket': self.basket,
  62. 'order_total': self.get_order_total(method),
  63. 'shipping_addr': self.get_shipping_address()}
  64. self.set_shipping_context(method)
  65. self.set_payment_context()
  66. if request.method == 'POST':
  67. response = self.handle_POST()
  68. elif request.method == 'GET':
  69. response = self.handle_GET()
  70. else:
  71. response = HttpResponseBadRequest()
  72. return response
  73. def set_shipping_context(self, method):
  74. if method:
  75. self.context['method'] = method
  76. self.context['shipping_total_excl_tax'] = method.basket_charge_excl_tax()
  77. self.context['shipping_total_incl_tax'] = method.basket_charge_incl_tax()
  78. def set_payment_context(self):
  79. method = self.co_data.payment_method()
  80. if method:
  81. self.context['payment_method'] = method
  82. def handle_GET(self):
  83. u"""
  84. Default behaviour is to set step as complete and redirect
  85. to the next step.
  86. """
  87. return self.get_success_response()
  88. def get_order_total(self, shipping_method):
  89. calc = OrderTotalCalculator(self.request)
  90. return calc.order_total_incl_tax(self.basket, shipping_method)
  91. def get_shipping_address(self):
  92. # Load address data into a blank address model
  93. addr_data = self.co_data.new_address_fields()
  94. if addr_data:
  95. return ShippingAddress(**addr_data)
  96. addr_id = self.co_data.user_address_id()
  97. if addr_id:
  98. try:
  99. return UserAddress._default_manager.get(pk=addr_id)
  100. except UserAddress.DoesNotExist:
  101. # This can happen if you reset all your tables and you still have
  102. # session data that refers to addresses that no longer exist
  103. pass
  104. return None
  105. def get_success_response(self):
  106. u"""
  107. Returns the appropriate redirect response if a checkout
  108. step has been successfully passed.
  109. """
  110. mark_step_as_complete(self.request)
  111. return HttpResponseRedirect(reverse(get_next_step(self.request)))
  112. def handle_POST(self):
  113. pass