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.

how_to_configure_shipping.rst 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. =========================
  2. How to configure shipping
  3. =========================
  4. Configuring shipping is not trivial. It generally requires creating a
  5. 'shipping' app within your project where you can define your own shipping
  6. methods as well as a 'repository' class which determines when methods are
  7. available.
  8. This recipe explains in more detail how Oscar models shipping as well as the
  9. steps involved in configuring shipping for your project.
  10. How Oscar handles shipping charges
  11. ----------------------------------
  12. Oscar uses a "repository" class to manage shipping charges. The class is used
  13. in two ways:
  14. * _It provides a list of shipping methods available to the user._ This is used to
  15. generate the content for the shipping methods page of checkout, where the user
  16. can choose a shipping method. The methods available generally depend on the
  17. user, the basket and the shipping address.
  18. * _It allows a shipping method to be retrieved based on a identifying code._ When
  19. a user selects a shipping method during checkout, it is persisted in the
  20. session using a code. This code is used to retrieve the chosen shipping
  21. method when it is required.
  22. The default shipping repository `can be seen here`_. It defaults to only
  23. providing one shipping method, which has no charge.
  24. .. note::
  25. Oscar's checkout process includes a page for choosing your shipping method.
  26. If there is only one method available for your basket then it will be chosen
  27. automatically and the user immediately redirected to the next step.
  28. Custom shipping charges
  29. -----------------------
  30. In order to control shipping logic for your project, you need to define your own
  31. repository class (see :doc:`how_to_override_a_core_class`). It normally makes
  32. sense to subclass the core ``Repository`` class and override the
  33. ``get_shipping_methods`` and ``find_by_code`` methods.
  34. Here's a very simple example where all shipping costs are a fixed price,
  35. irrespective of basket and shipping address::
  36. # myproject/shipping/repository.py
  37. from decimal import Decimal as D
  38. from oscar.apps.shipping import repository, methods as core_methods
  39. class Repository(repository.Repository):
  40. methods = [core_methods.FixedPrice(D('9.99'))]
  41. def get_shipping_methods(self, user, basket, shipping_addr=None, **kwargs):
  42. return self.prime_methods(basket, self.methods)
  43. def find_by_code(self, code, basket):
  44. for method in self.methods:
  45. if code == method.code:
  46. return self.prime_method(basket, method)
  47. Note that both these methods must return 'primed' method instances, which means
  48. the basket instance has been injected into the method. This allows the method
  49. instance to return the shipping charge directly without requiring the basket to
  50. be passed again (which is useful in templates).
  51. As you can see the ``get_shipping_methods`` can depend on several things:
  52. * the user in question (e.g., staff get cheaper shipping rates)
  53. * the basket (e.g., shipping is charged based on the weight of the basket)
  54. * the shipping address (e.g., overseas shipping is more expensive)
  55. Here's a more involved example repository that has two fixed price charges::
  56. # myproject/shipping/repository.py
  57. from decimal import Decimal as D
  58. from oscar.apps.shipping import repository, methods as core_methods
  59. # We create subclasses so we can give them different codes and names
  60. class Standard(methods.FixedPrice):
  61. code = 'standard'
  62. name = _("Standard shipping")
  63. class Express(methods.FixedPrice):
  64. code = 'express'
  65. name = _("Express shipping")
  66. class Repository(repository.Repository):
  67. methods = [Standard(D('10.00')), Express(D('20.00'))]
  68. def get_shipping_methods(self, user, basket, shipping_addr=None, **kwargs):
  69. return self.prime_methods(basket, self.methods)
  70. def find_by_code(self, code, basket):
  71. for method in self.methods:
  72. if code == method.code:
  73. return self.prime_method(basket, method)
  74. .. _`can be seen here`: https://github.com/tangentlabs/django-oscar/blob/master/oscar/apps/shipping/repository.py
  75. Shipping methods
  76. ----------------
  77. The repository class is responsible for return shipping method instances. Oscar
  78. defines several of these but it is easy to write your own, their interface is
  79. simple.
  80. The base shipping method class ``oscar.apps.shipping.base.ShippingMethod`` (that
  81. all shipping methods should subclass has API:
  82. .. autoclass:: oscar.apps.shipping.base.ShippingMethod
  83. :members:
  84. Core shipping methods
  85. ~~~~~~~~~~~~~~~~~~~~~
  86. The shipping methods that ship with Oscar are:
  87. * ``oscar.apps.shipping.methods.Free``. No shipping charges.
  88. * ``oscar.apps.shipping.methods.WeightBased``. This is a model-driven method
  89. that uses two models: ``WeightBased`` and ``WeightBand`` to provide charges
  90. for different weight bands. By default, the method will calculate the weight
  91. of a product by looking for a 'weight' attribute although this can be
  92. configured.
  93. * ``oscar.apps.shipping.methods.FixedPrice``. This simply charges a fixed price for
  94. shipping, irrespective of the basket contents.
  95. * ``oscar.apps.shipping.methods.OrderAndItemCharges``. This is a model which
  96. specifies a per-order and a per-item level charge.
  97. To apply your domain logic for shipping, you will need to override
  98. the default repository class (see :doc:`how_to_override_a_core_class`) and alter
  99. the implementation of the ``get_shipping_methods`` method. This method
  100. should return a list of "shipping method" classes already instantiated
  101. and holding a reference to the basket instance.
  102. Building a custom shipping method
  103. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  104. At a minimum, a custom shipping method class should define a ``code`` and
  105. ``name`` attribute to distinguish it from other methods. It is also normal to
  106. override the ``basket_charge_incl_tax`` and ``basket_charge_excl_tax`` methods
  107. to implement your custom shipping charge logic.
  108. .. tip::
  109. Most of the shipping logic should live in the repository class, the method
  110. instance is only responsble for returning the charge for a given basket.