Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

core_views.py 5.4KB

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