Django-URLs TypeError: Die Ansicht muss aufrufbar oder eine Liste / ein Tupel sein, wenn include ()

111

Nach dem Upgrade auf Django 1.10 wird folgende Fehlermeldung angezeigt:

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

Meine urls.py lautet wie folgt:

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

Der vollständige Traceback lautet:

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().
Alasdair
quelle
Wenn wir Dekorateure verwenden und wenn sie nichts zurückgeben. Auch in diesem Fall erhalten wir oben Fehler. Vor kurzem habe ich diesen Fehler bekommen.
anjaneyulubatta505
@AnjaneyuluBatta Ja, wenn ein Dekorateur eine Ansicht nicht zurückgibt None, wird sie implizit zurückgegeben , was eine TypeErrorwie oben verursachen würde .
Alasdair

Antworten:

257

In Django 1.10 können Sie Ansichten nicht mehr als Zeichenfolge (z. B. 'myapp.views.home') in Ihren URL-Mustern angeben .

Die Lösung besteht darin, Ihre zu aktualisieren urls.py, um die aufrufbare Ansicht einzuschließen. Dies bedeutet, dass Sie die Ansicht in Ihre importieren müssen urls.py. Wenn Ihre URL-Muster keine Namen haben, ist jetzt ein guter Zeitpunkt, um einen hinzuzufügen, da das Umkehren mit dem gepunkteten Python-Pfad nicht mehr funktioniert.

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

Wenn es viele Ansichten gibt, kann es unpraktisch sein, sie einzeln zu importieren. Eine Alternative besteht darin, das Ansichtsmodul aus Ihrer App zu importieren.

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

Beachten Sie, dass wir verwendet haben , as myapp_viewsund as auth_views, was uns die importiert werden können views.pyvon mehreren Anwendungen , ohne sie kollidierende.

Weitere Informationen zu finden Sie in den Django URL Dispatcher-Dokumentenurlpatterns .

Alasdair
quelle
Was ist mit klassenbasierten Ansichten?
Rishabh Agrahari
2
Sie konnten den gepunkteten Zeichenfolgenpfad noch nie für klassenbasierte Ansichten verwenden, daher sind sie für diese Frage nicht relevant.
Alasdair
Ich möchte, dass die Änderung wie diese mit einem Helfer (einem migrierenden Skript) geliefert wird, da Sie auch kein Präfix verwenden können. import_moduleDies kann Ihnen helfen, eine eigene Suche als Wrapper für die alte Zeichenfolge zu erstellen, wenn Tausende von URLs darauf warten, dass Sie sie aktualisieren.
Sławomir Lenart
Sie müssen auch noch andere Pakete importieren - Import aus der Import-URL von django.conf.urls. Bitte korrigieren Sie Ihre Lösung.
WebComer
1
@WebComer Ich habe den URL-Import nicht in die Frage / Antwort aufgenommen, da diese beim Upgrade auf Django 1.10 gleich bleiben (es sei denn, Sie haben django.conf.urls.defaultsvon Django 1.5 oder früher). Ich habe die Importe wie gewünscht hinzugefügt, bin mir aber nicht sicher, ob dies eine gute Idee ist, da sich die Importe in Django 2.0 erneut ändern. Wenn Sie die richtigen Importe wissen möchten, sind die Dokumente für Ihre Version von Django (z. B. 1.11 , 2.0 ) der beste Ort, um nachzuschauen.
Alasdair
3

Dieser Fehler bedeutet nur, dass dies myapp.views.homenicht wie eine Funktion aufgerufen werden kann. Es ist in der Tat eine Zeichenfolge. Während Ihre Lösung in Django 1.9 funktioniert, wird dennoch eine Warnung ausgegeben, die besagt, dass dies ab Version 1.10 nicht mehr möglich ist. Genau das ist passiert. Die vorherige Lösung von @Alasdair importiert die erforderlichen Ansichtsfunktionen entweder über from myapp import views as myapp_views oder in das Skript from myapp.views import home, contact

hAcKnRoCk
quelle
1

Möglicherweise wird dieser Fehler auch angezeigt, wenn bei einer Ansicht und einem Modul ein Namenskonflikt auftritt. Ich habe den Fehler erhalten, als ich meine Ansichtsdateien unter dem Ordner "Ansichten" verteilte /views/view1.py, /views/view2.pyund ein Modell mit dem Namen "table.py" in "view2.py" importierte, das zufällig ein Name einer Ansicht in "view1.py" war. Das Benennen der Ansicht funktioniert also als v_table(request,id) hilfreich.

binboavetonik
quelle
0

Ihr Code ist

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

Ändern Sie es beim Importieren in die folgende include()Funktion:

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