title: Error importing storage module.whitenoise.django
body: <p>I'm trying to deploy a basic Django app to Heroku, but am getting an error when I try to deploy.</p>
  
  <p>It looks like the error is with <em>whitenoise</em>. I have <em>six</em> installed as part of my requirements so it should handle urllib.parse.</p>
  
  <p>Here is the error:</p>
  
  <pre><code>remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/files/storage.py", line 290, in get_storage_class
  remote:            raise ImproperlyConfigured('Error importing storage module %s: "%s"' % (module, e))
  remote:        django.core.exceptions.ImproperlyConfigured: Error importing storage module whitenoise.django: "No module named urllib.parse"
  remote: 
  remote:  !     Error while running '$ python manage.py collectstatic --noinput'.
  </code></pre>
  
  <p>Here is the full stack:</p>
  
  <pre><code>remote: 
  remote: -----&gt; Python app detected
  remote: -----&gt; Uninstalling stale dependencies
  remote:        Uninstalling DateTime-4.1.1:
  remote:          Successfully uninstalled DateTime-4.1.1
  remote:        Uninstalling simplejson-3.8.2:
  remote:          Successfully uninstalled simplejson-3.8.2
  remote: -----&gt; Noticed cffi. Bootstrapping libffi.
  remote:      $ pip install -r requirements.txt
  remote:        Collecting altgraph==0.10.2 (from -r requirements.txt (line 1))
  remote:          Downloading altgraph-0.10.2.tar.gz (481kB)
  remote:        Collecting bdist-mpkg==0.5.0 (from -r requirements.txt (line 2))
  remote:          Downloading bdist_mpkg-0.5.0.tar.gz
  remote:        Collecting bpython==0.12 (from -r requirements.txt (line 3))
  remote:          Downloading bpython-0.12.tar.gz (130kB)
  remote:        Collecting csvkit==0.7.3 (from -r requirements.txt (line 4))
  remote:          Downloading csvkit-0.7.3.tar.gz
  remote:        Collecting Cython==0.19.2 (from -r requirements.txt (line 5))
  remote:          Downloading Cython-0.19.2-cp27-cp27m-manylinux1_x86_64.whl (4.0MB)
  remote:        Collecting dbf==0.94.3 (from -r requirements.txt (line 6))
  remote:          Downloading dbf-0.94.003.tar.gz (79kB)
  remote:        Collecting dj-database-url==0.4.1 (from -r requirements.txt (line 7))
  remote:          Downloading dj-database-url-0.4.1.tar.gz
  remote:        Collecting Django==1.5.4 (from -r requirements.txt (line 8))
  remote:          Downloading Django-1.5.4.tar.gz (8.1MB)
  remote:        Collecting future==0.11.2 (from -r requirements.txt (line 9))
  remote:          Downloading future-0.11.2.tar.gz (321kB)
  remote:        Collecting futures==3.0.5 (from -r requirements.txt (line 10))
  remote:          Downloading futures-3.0.5-py2-none-any.whl
  remote:        Collecting greenlet==0.4.1 (from -r requirements.txt (line 11))
  remote:          Downloading greenlet-0.4.1.zip (75kB)
  remote:        Collecting grequests==0.2.0 (from -r requirements.txt (line 12))
  remote:          Downloading grequests-0.2.0.tar.gz
  remote:        Collecting gunicorn==19.6.0 (from -r requirements.txt (line 13))
  remote:          Downloading gunicorn-19.6.0-py2.py3-none-any.whl (114kB)
  remote:        Collecting humanize==0.5 (from -r requirements.txt (line 14))
  remote:          Downloading humanize-0.5.tar.gz
  remote:        Collecting iso8601==0.1.8 (from -r requirements.txt (line 15))
  remote:          Downloading iso8601-0.1.8.tar.gz
  remote:        Collecting livestreamer==1.12.2 (from -r requirements.txt (line 16))
  remote:          Downloading livestreamer-1.12.2.tar.gz (430kB)
  remote:        Collecting macholib==1.5.1 (from -r requirements.txt (line 17))
  remote:          Downloading macholib-1.5.1.tar.gz (454kB)
  remote:        Collecting modulegraph==0.10.4 (from -r requirements.txt (line 18))
  remote:          Downloading modulegraph-0.10.4.tar.gz (532kB)
  remote:        Collecting MySQL-python==1.2.4 (from -r requirements.txt (line 19))
  remote:          Downloading MySQL-python-1.2.4.zip (113kB)
  remote:        Collecting openpyxl==2.0.3 (from -r requirements.txt (line 20))
  remote:          Downloading openpyxl-2.0.3.tar.gz (113kB)
  remote:        Collecting py2app==0.7.3 (from -r requirements.txt (line 21))
  remote:          Downloading py2app-0.7.3.tar.gz (1.2MB)
  remote:        Collecting pycrypto==2.6.1 (from -r requirements.txt (line 22))
  remote:          Downloading pycrypto-2.6.1.tar.gz (446kB)
  remote:        Collecting pycurl==7.19.0.2 (from -r requirements.txt (line 23))
  remote:          Downloading pycurl-7.19.0.2.tar.gz (89kB)
  remote:        Collecting Pygments==1.6 (from -r requirements.txt (line 24))
  remote:          Downloading Pygments-1.6.tar.gz (1.4MB)
  remote:        Collecting pyOpenSSL==0.13.1 (from -r requirements.txt (line 25))
  remote:          Downloading pyOpenSSL-0.13.1.tar.gz (254kB)
  remote:        Collecting pyparsing==2.0.1 (from -r requirements.txt (line 26))
  remote:          Downloading pyparsing-2.0.1.tar.gz (1.1MB)
  remote:        Collecting python-dateutil==1.5 (from -r requirements.txt (line 27))
  remote:          Downloading python-dateutil-1.5.tar.gz (233kB)
  remote:        Collecting pytz==2013.7 (from -r requirements.txt (line 28))
  remote:          Downloading pytz-2013.7.tar.bz2 (177kB)
  remote:        Collecting requests==2.0.1 (from -r requirements.txt (line 29))
  remote:          Downloading requests-2.0.1-py2.py3-none-any.whl (439kB)
  remote:        Collecting singledispatch==3.4.0.3 (from -r requirements.txt (line 30))
  remote:          Downloading singledispatch-3.4.0.3-py2.py3-none-any.whl
  remote:        Collecting six==1.4.1 (from -r requirements.txt (line 31))
  remote:          Downloading six-1.4.1.tar.gz
  remote:        Collecting SQLAlchemy==0.9.4 (from -r requirements.txt (line 32))
  remote:          Downloading SQLAlchemy-0.9.4.tar.gz (4.5MB)
  remote:        Collecting virtualenv==15.0.3 (from -r requirements.txt (line 33))
  remote:          Downloading virtualenv-15.0.3-py2.py3-none-any.whl (3.5MB)
  remote:        Collecting whitenoise==3.2.2 (from -r requirements.txt (line 34))
  remote:          Downloading whitenoise-3.2.2-py2.py3-none-any.whl
  remote:        Collecting xattr==0.6.4 (from -r requirements.txt (line 35))
  remote:          Downloading xattr-0.6.4.tar.gz
  remote:        Collecting xlrd==0.9.3 (from -r requirements.txt (line 36))
  remote:          Downloading xlrd-0.9.3.tar.gz (178kB)
  remote:        Collecting zope.interface==4.1.1 (from -r requirements.txt (line 37))
  remote:          Downloading zope.interface-4.1.1.tar.gz (864kB)
  remote:        Collecting gevent (from grequests==0.2.0-&gt;-r requirements.txt (line 12))
  remote:          Downloading gevent-1.1.2-cp27-cp27m-manylinux1_x86_64.whl (1.3MB)
  remote:        Collecting jdcal (from openpyxl==2.0.3-&gt;-r requirements.txt (line 20))
  remote:          Downloading jdcal-1.3.tar.gz
  remote:        Installing collected packages: altgraph, bdist-mpkg, Pygments, bpython, xlrd, python-dateutil, SQLAlchemy, jdcal, openpyxl, dbf, csvkit, Cython, dj-database-url, Django, future, futures, greenlet, gevent, requests, grequests, gunicorn, humanize, iso8601, six, singledispatch, livestreamer, macholib, modulegraph, MySQL-python, py2app, pycrypto, pycurl, pyOpenSSL, pyparsing, pytz, virtualenv, whitenoise, xattr, zope.interface
  remote:          Running setup.py install for altgraph: started
  remote:            Running setup.py install for altgraph: finished with status 'done'
  remote:          Running setup.py install for bdist-mpkg: started
  remote:            Running setup.py install for bdist-mpkg: finished with status 'done'
  remote:          Running setup.py install for Pygments: started
  remote:            Running setup.py install for Pygments: finished with status 'done'
  remote:          Running setup.py install for bpython: started
  remote:            Running setup.py install for bpython: finished with status 'done'
  remote:          Running setup.py install for xlrd: started
  remote:            Running setup.py install for xlrd: finished with status 'done'
  remote:          Running setup.py install for python-dateutil: started
  remote:            Running setup.py install for python-dateutil: finished with status 'done'
  remote:          Running setup.py install for SQLAlchemy: started
  remote:            Running setup.py install for SQLAlchemy: finished with status 'done'
  remote:          Running setup.py install for jdcal: started
  remote:            Running setup.py install for jdcal: finished with status 'done'
  remote:          Running setup.py install for openpyxl: started
  remote:            Running setup.py install for openpyxl: finished with status 'done'
  remote:          Running setup.py install for dbf: started
  remote:            Running setup.py install for dbf: finished with status 'done'
  remote:          Running setup.py install for csvkit: started
  remote:            Running setup.py install for csvkit: finished with status 'done'
  remote:          Running setup.py install for dj-database-url: started
  remote:            Running setup.py install for dj-database-url: finished with status 'done'
  remote:          Running setup.py install for Django: started
  remote:            Running setup.py install for Django: finished with status 'done'
  remote:          Running setup.py install for future: started
  remote:            Running setup.py install for future: finished with status 'done'
  remote:          Running setup.py install for greenlet: started
  remote:            Running setup.py install for greenlet: finished with status 'done'
  remote:          Found existing installation: requests 2.11.1
  remote:            Uninstalling requests-2.11.1:
  remote:              Successfully uninstalled requests-2.11.1
  remote:          Running setup.py install for grequests: started
  remote:            Running setup.py install for grequests: finished with status 'done'
  remote:          Running setup.py install for humanize: started
  remote:            Running setup.py install for humanize: finished with status 'done'
  remote:          Running setup.py install for iso8601: started
  remote:            Running setup.py install for iso8601: finished with status 'done'
  remote:          Running setup.py install for six: started
  remote:            Running setup.py install for six: finished with status 'done'
  remote:          Running setup.py install for livestreamer: started
  remote:            Running setup.py install for livestreamer: finished with status 'done'
  remote:          Running setup.py install for macholib: started
  remote:            Running setup.py install for macholib: finished with status 'done'
  remote:          Running setup.py install for modulegraph: started
  remote:            Running setup.py install for modulegraph: finished with status 'done'
  remote:          Running setup.py install for MySQL-python: started
  remote:            Running setup.py install for MySQL-python: finished with status 'done'
  remote:          Running setup.py install for py2app: started
  remote:            Running setup.py install for py2app: finished with status 'done'
  remote:          Running setup.py install for pycrypto: started
  remote:            Running setup.py install for pycrypto: finished with status 'done'
  remote:          Running setup.py install for pycurl: started
  remote:            Running setup.py install for pycurl: finished with status 'done'
  remote:          Running setup.py install for pyOpenSSL: started
  remote:            Running setup.py install for pyOpenSSL: finished with status 'done'
  remote:          Running setup.py install for pyparsing: started
  remote:            Running setup.py install for pyparsing: finished with status 'done'
  remote:          Found existing installation: pytz 2016.7
  remote:            Uninstalling pytz-2016.7:
  remote:              Successfully uninstalled pytz-2016.7
  remote:          Running setup.py install for pytz: started
  remote:            Running setup.py install for pytz: finished with status 'done'
  remote:          Running setup.py install for xattr: started
  remote:            Running setup.py install for xattr: finished with status 'done'
  remote:          Found existing installation: zope.interface 4.3.2
  remote:            Uninstalling zope.interface-4.3.2:
  remote:              Successfully uninstalled zope.interface-4.3.2
  remote:          Running setup.py install for zope.interface: started
  remote:            Running setup.py install for zope.interface: finished with status 'done'
  remote:        Successfully installed Cython-0.19.2 Django-1.5.4 MySQL-python-1.2.4 Pygments-1.6 SQLAlchemy-0.9.4 altgraph-0.10.2 bdist-mpkg-0.5.0 bpython-0.12 csvkit-0.7.3 dbf-0.94.3 dj-database-url-0.4.1 future-0.11.2 futures-3.0.5 gevent-1.1.2 greenlet-0.4.1 grequests-0.2.0 gunicorn-19.6.0 humanize-0.5 iso8601-0.1.8 jdcal-1.3 livestreamer-1.12.2 macholib-1.5.1 modulegraph-0.10.4 openpyxl-2.0.3 py2app-0.7.3 pyOpenSSL-0.13.1 pycrypto-2.6.1 pycurl-7.19.0.2 pyparsing-2.0.1 python-dateutil-1.5 pytz-2013.7 requests-2.0.1 singledispatch-3.4.0.3 six-1.4.1 virtualenv-15.0.3 whitenoise-3.2.2 xattr-0.6.4 xlrd-0.9.3 zope.interface-4.1.1
  remote: 
  remote:      $ python manage.py collectstatic --noinput
  remote:        Traceback (most recent call last):
  remote:          File "manage.py", line 10, in &lt;module&gt;
  remote:            execute_from_command_line(sys.argv)
  remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 453, in execute_from_command_line
  remote:            utility.execute()
  remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 392, in execute
  remote:            self.fetch_command(subcommand).run_from_argv(self.argv)
  remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 272, in fetch_command
  remote:            klass = load_command_class(app_name, subcommand)
  remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 78, in load_command_class
  remote:            return module.Command()
  remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 58, in __init__
  remote:            self.storage.path('')
  remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/utils/functional.py", line 204, in inner
  remote:            self._setup()
  remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/storage.py", line 307, in _setup
  remote:            self._wrapped = get_storage_class(settings.STATICFILES_STORAGE)()
  remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/files/storage.py", line 290, in get_storage_class
  remote:            raise ImproperlyConfigured('Error importing storage module %s: "%s"' % (module, e))
  remote:        django.core.exceptions.ImproperlyConfigured: Error importing storage module whitenoise.django: "No module named urllib.parse"
  remote: 
  remote:  !     Error while running '$ python manage.py collectstatic --noinput'.
  remote:        See traceback above for details.
  remote: 
  remote:        You may need to update application code to resolve this error.
  remote:        Or, you can disable collectstatic for this application:
  remote: 
  remote:           $ heroku config:set DISABLE_COLLECTSTATIC=1
  remote: 
  remote:        https://devcenter.heroku.com/articles/django-assets
  remote:  !     Push rejected, failed to compile Python app.
  </code></pre>