Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

session.py 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. from django.db.models import get_model
  2. from oscar.core.loading import get_class
  3. Repository = get_class('shipping.repository', 'Repository')
  4. OrderTotalCalculator = get_class(
  5. 'checkout.calculators', 'OrderTotalCalculator')
  6. CheckoutSessionData = get_class(
  7. 'checkout.utils', 'CheckoutSessionData')
  8. ShippingAddress = get_model('order', 'ShippingAddress')
  9. UserAddress = get_model('address', 'UserAddress')
  10. class CheckoutSessionMixin(object):
  11. """
  12. Mixin to provide common functionality shared between checkout views.
  13. """
  14. def dispatch(self, request, *args, **kwargs):
  15. # Assign the checkout session manager so it's available in all checkout
  16. # views.
  17. self.checkout_session = CheckoutSessionData(request)
  18. return super(CheckoutSessionMixin, self).dispatch(
  19. request, *args, **kwargs)
  20. def get_context_data(self, **kwargs):
  21. """
  22. Assign common template variables to the context.
  23. """
  24. ctx = super(CheckoutSessionMixin, self).get_context_data(**kwargs)
  25. basket = self.request.basket
  26. shipping_address = self.get_shipping_address(basket)
  27. shipping_method = self.get_shipping_method(
  28. basket, shipping_address)
  29. ctx['shipping_address'] = shipping_address
  30. ctx['shipping_method'] = shipping_method
  31. if basket and shipping_method:
  32. ctx['order_total'] = self.get_order_totals(basket, shipping_method)
  33. return ctx
  34. def get_shipping_address(self, basket):
  35. """
  36. Return the (unsaved) shipping address for this checkout session.
  37. If the shipping address was entered manually, then we instantiate a
  38. ``ShippingAddress`` model with the appropriate form data (which is
  39. saved in the session).
  40. If the shipping address was selected from the user's address book,
  41. then we convert the ``UserAddress`` to a ``ShippingAddress``.
  42. The ``ShippingAddress`` instance is not saved as sometimes you need a
  43. shipping address instance before the order is placed. For example, if
  44. you are submitting fraud information as part of a payment request.
  45. The ``OrderPlacementMixin.create_shipping_address`` method is
  46. responsible for saving a shipping address when an order is placed.
  47. """
  48. if not basket.is_shipping_required():
  49. return None
  50. addr_data = self.checkout_session.new_shipping_address_fields()
  51. if addr_data:
  52. # Load address data into a blank shipping address model
  53. return ShippingAddress(**addr_data)
  54. addr_id = self.checkout_session.user_address_id()
  55. if addr_id:
  56. try:
  57. address = UserAddress._default_manager.get(pk=addr_id)
  58. except UserAddress.DoesNotExist:
  59. # An address was selected but now it has disappeared. This can
  60. # happen if the customer flushes their address book midway
  61. # through checkout. No idea why they would do this but it can
  62. # happen. Checkouts are highly vulnerable to race conditions
  63. # like this.
  64. return None
  65. else:
  66. # Copy user address data into a blank shipping address instance
  67. shipping_addr = ShippingAddress()
  68. address.populate_alternative_model(shipping_addr)
  69. return shipping_addr
  70. def get_shipping_method(self, basket, shipping_address=None, **kwargs):
  71. """
  72. Return the selected shipping method instance from this checkout session
  73. The shipping address is passed as we need to check that the method
  74. stored in the session is still valid for the shippinga address.
  75. """
  76. code = self.checkout_session.shipping_method_code(basket)
  77. methods = Repository().get_shipping_methods(
  78. user=self.request.user, basket=basket,
  79. shipping_addr=shipping_address, request=self.request)
  80. for method in methods:
  81. if method.code == code:
  82. return method
  83. def get_order_totals(self, basket, shipping_method, **kwargs):
  84. """
  85. Returns the total for the order with and without tax (as a tuple)
  86. """
  87. return OrderTotalCalculator(self.request).calculate(
  88. basket, shipping_method, **kwargs)