Django URLs TypeError: view must be a callable or a list/tuple in the case of include()

After upgrading to Django 1.10, I get the error:

    TypeError: view must be a callable or a list/tuple in the case of include().

My urls.py is as follows:

    from django.conf.urls import include, url

    urlpatterns = [
        url(r'^$', 'myapp.views.home'),
        url(r'^contact/$', 'myapp.views.contact'),
        url(r'^login/$', 'django.contrib.auth.views.login'),
    ]

The full traceback is:

    Traceback (most recent call last):
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
        fn(*args, **kwargs)
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 121, in inner_run
        self.check(display_num_errors=True)
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/base.py", line 385, in check
        include_deployment_checks=include_deployment_checks,
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/management/base.py", line 372, in _run_checks
        return checks.run_checks(**kwargs)
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/registry.py", line 81, in run_checks
        new_errors = check(app_configs=app_configs)
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/urls.py", line 14, in check_url_config
        return check_resolver(resolver)
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/core/checks/urls.py", line 24, in check_resolver
        for pattern in resolver.url_patterns:
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/functional.py", line 35, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/urls/resolvers.py", line 310, in url_patterns
        patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/utils/functional.py", line 35, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/urls/resolvers.py", line 303, in urlconf_module
        return import_module(self.urlconf_name)
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
        __import__(name)
      File "/Users/alasdair/dev/urlproject/urlproject/urls.py", line 28, in <module>
        url(r'^$', 'myapp.views.home'),
      File "/Users/alasdair/.virtualenvs/django110/lib/python2.7/site-packages/django/conf/urls/__init__.py", line 85, in url
        raise TypeError('view must be a callable or a list/tuple in the case of include().')
    TypeError: view must be a callable or a list/tuple in the case of include().

Django 1.10 no longer allows you to specify views as a string (e.g. 'myapp.views.home') in your URL patterns.

The solution is to update your urls.py to include the view callable. This means that you have to import the view in your urls.py. If your URL patterns don't have names, then now is a good time to add one, because reversing with the dotted python path no longer works.

    from django.conf.urls import include, url

    from django.contrib.auth.views import login
    from myapp.views import home, contact

    urlpatterns = [
        url(r'^$', home, name='home'),
        url(r'^contact/$', contact, name='contact'),
        url(r'^login/$', login, name='login'),
    ]

If there are many views, then importing them individually can be inconvenient. An alternative is to import the views module from your app.

    from django.conf.urls import include, url

    from django.contrib.auth import views as auth_views
    from myapp import views as myapp_views

    urlpatterns = [
        url(r'^$', myapp_views.home, name='home'),
        url(r'^contact/$', myapp_views.contact, name='contact'),
        url(r'^login/$', auth_views.login, name='login'),
    ]

Note that we have used as myapp_views and as auth_views, which allows us to import the views.py from multiple apps without them clashing.

See the Django URL dispatcher docs for more information about urlpatterns.

From: stackoverflow.com/q/38744285

Back to homepage or read more recommendations: