Django URL-адреса TypeError: представление должно быть вызываемым или списком / кортежем в случае include ()

После обновления до Django 1.10 я получаю сообщение об ошибке:

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

Мой urls.py выглядит следующим образом:

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'),
]

Полная трассировка:

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().

person Alasdair    schedule 03.08.2016    source источник
comment
Если мы используем декораторы для просмотра и если они ничего не возвращают. В этом случае мы также получаем указанную выше ошибку. недавно я получил эту ошибку.   -  person anjaneyulubatta505    schedule 31.12.2016
comment
@AnjaneyuluBatta: да, если декоратор не возвращает представление, он неявно возвращает None, что вызовет TypeError, как указано выше.   -  person Alasdair    schedule 06.01.2017


Ответы (4)


Django 1.10 больше не позволяет указывать представления в виде строки (например, 'myapp.views.home') в шаблонах URL.

Решение состоит в том, чтобы обновить ваш urls.py, чтобы включить в него вызываемый вид. Это означает, что вам нужно импортировать представление в свой urls.py. Если у ваших шаблонов URL-адресов нет имен, то сейчас самое время добавить его, потому что реверсирование пути Python с точками больше не работает.

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'),
]

Если просмотров много, то импорт их по отдельности может быть неудобным. Альтернативой является импорт модуля представлений из вашего приложения.

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'),
]

Обратите внимание, что мы использовали as myapp_views и as auth_views, что позволяет нам импортировать views.py из нескольких приложений без их конфликтов.

Дополнительную информацию о urlpatterns.

person Alasdair    schedule 03.08.2016
comment
А как насчет представлений на основе классов? - person Rishabh Agrahari; 10.03.2017
comment
Вы никогда не могли использовать путь к строке с точками для представлений на основе классов, поэтому они не имеют отношения к этому вопросу. - person Alasdair; 10.03.2017
comment
Я хочу, чтобы подобное изменение было связано с неким помощником (скриптом миграции), потому что вы также не можете использовать префикс. import_module может помочь вам создать собственный поиск в качестве оболочки для старой строки в случае, когда тысячи URL-адресов ждут, когда вы их обновите. - person Sławomir Lenart; 19.12.2017
comment
Вам все равно придется импортировать другие пакеты - импорт из django.conf.urls import url. Исправьте свое решение. - person WebComer; 22.11.2018
comment
@WebComer Я не включил импорт URL-адреса в вопрос / ответ, потому что они остаются такими же при обновлении до Django 1.10 (если у вас нет django.conf.urls.defaults из Django 1.5 или более ранней версии). Я добавил импорт, как вы просили, но я не уверен, что это хорошая идея, поскольку импорт снова изменился в Django 2.0. Если вы хотите знать правильный импорт, тогда документы для вашей версии Django (например, 1.11, 2.0) являются лучшими место смотреть. - person Alasdair; 22.11.2018
comment
@Alasdair Мне нравится отмечать разницу в версиях. Вы можете указать варианты версий в своем ответе, это даст нам больше информации. По крайней мере, для меня, поскольку я новичок в Django. Также будет оценена хорошая ссылка или рассказ об эволюции URL-адресов, так как есть много хороших устаревших руководств. - person WebComer; 25.11.2018
comment
@WebComer Этот вопрос / ответ предназначен для того, чтобы помочь исправить конкретную ошибку, а не для получения истории URL-адресов Django. Мы уходим от темы. Не могли бы вы удалить свои комментарии, чтобы ответ был аккуратным? Если в руководстве по-прежнему отображается этот старый синтаксис URL, значит, он устарел на три года, поэтому я бы не рекомендовал его новым пользователям. - person Alasdair; 26.11.2018

Эта ошибка просто означает, что myapp.views.home нельзя вызывать, например функцию. На самом деле это строка. Хотя ваше решение работает в django 1.9, оно, тем не менее, выдает предупреждение о том, что оно устареет с версии 1.10 и далее, что и произошло. Предыдущее решение от @Alasdair импортирует необходимые функции просмотра в скрипт через from myapp import views as myapp_views или from myapp.views import home, contact

person hAcKnRoCk    schedule 08.08.2016

Вы также можете получить эту ошибку, если у вас есть конфликт имен представления и модуля. У меня возникает ошибка, когда я распространяю файлы представления в папке представлений /views/view1.py, /views/view2.py и импортировал некоторую модель с именем table.py в view2.py, которая оказалась именем представления в view1.py. Так что присвоение функции просмотра v_table(request,id) помогло.

person binboavetonik    schedule 06.05.2018

Ваш код

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

измените его на следующее, когда вы импортируете include() функцию:

urlpatterns = [
    url(r'^$', views.home),
    url(r'^contact/$', views.contact),
    url(r'^login/$', views.login),
]
person Nishant Soni    schedule 25.08.2018