Search code examples
djangodjango-oscar

How to fix django-oscar shipping UnboundLocalError?


I want to add a shipping methods to django-oscar, but I'm getting the UnboundLocalError error even though I've done everything on the document page.

Request Method: GET
Request URL:    http://127.0.0.1:8000/checkout/shipping-address/
Django Version: 2.1.7
Exception Type: UnboundLocalError
Exception Value:    
local variable 'methods' referenced before assignment

repository.py

from oscar.apps.shipping import repository
from . import methods

class Repository(repository.Repository):

    def get_available_shipping_methods(self, basket, user=None, shipping_addr=None, request=None, **kwargs):
        methods = (methods.Standard(),)
        if shipping_addr and shipping_addr.country.code == 'GB':
            # Express is only available in the UK
            methods = (methods.Standard(), methods.Express())
        return methods

methods.py

from oscar.apps.shipping import methods
from oscar.core import prices
from decimal import Decimal as D

class Standard(methods.Base):
    code = 'standard'
    name = 'Shipping (Standard)'

    def calculate(self, basket):
        return prices.Price(
            currency=basket.currency,
            excl_tax=D('5.00'), incl_tax=D('5.00'))

class Express(methods.Base):
    code = 'express'
    name = 'Shipping (Express)'

    def calculate(self, basket):
        return prices.Price(
            currency=basket.currency,
            excl_tax=D('4.00'), incl_tax=D('4.00'))

Solution

  • I can see that is in the docs, but they look to have a bug in them.

    With UnboundLocalError you're essentially looking at a scope issue. A really simple example would be;

    x = 10
    def foo():
        x += 1
        print x
    foo()
    

    When foo executes x isn't available to foo. So change the import slightly to avoid this;

    from oscar.apps.shipping import repository
    from . import methods as shipping_methods
    
    class Repository(repository.Repository):
    
        def get_available_shipping_methods(self, basket, user=None, shipping_addr=None, request=None, **kwargs):
            methods = (shipping_methods.Standard(),)
            if shipping_addr and shipping_addr.country.code == 'GB':
                # Express is only available in the UK
                methods = (shipping_methods.Standard(), shipping_methods.Express())
            return methods