URL di Django TypeError: la vista deve essere una chiamata o una lista / tupla nel caso di include ()


111

Dopo l'aggiornamento a Django 1.10, ottengo l'errore:

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

Il mio urls.py è il seguente:

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

Il traceback completo è:

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

Se usiamo decoratori a vista e se non restituiamo nulla. Anche in questo caso si ottiene l'errore di cui sopra. recentemente ho ricevuto questo errore.
— anjaneyulubatta505

@AnjaneyuluBatta sì, se un decoratore non restituisce una vista, restituisce implicitamente None, il che causerebbe un TypeErrorcome sopra.
— Alasdair

Risposte:


257

Django 1.10 non ti consente più di specificare le viste come una stringa (ad esempio 'myapp.views.home') nei tuoi pattern URL.

La soluzione è aggiornare il tuo urls.pyper includere la vista richiamabile. Ciò significa che devi importare la visualizzazione nel tuo file urls.py. Se i tuoi pattern URL non hanno nomi, allora è un buon momento per aggiungerne uno, perché l'inversione con il percorso python punteggiato non funziona più.

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

Se sono presenti molte visualizzazioni, importarle singolarmente può essere scomodo. Un'alternativa è importare il modulo delle visualizzazioni dalla tua 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'),
]

Nota che abbiamo usato as myapp_viewse as auth_views, che ci consente di importare il views.pyda più app senza che si scontrino.

Consulta i documenti del dispatcher dell'URL Django per ulteriori informazioni su urlpatterns.


E le visualizzazioni basate sulla classe?
— Rishabh Agrahari

2
Non sei mai stato in grado di utilizzare il percorso della stringa punteggiata per le visualizzazioni basate sulla classe, quindi non sono rilevanti per questa domanda.
— Alasdair

Vorrei vedere il cambiamento come questo venire con qualche aiuto (uno script di migrazione), perché non sei in grado di usare anche il prefisso. import_modulepotrebbe aiutarti a creare la tua ricerca come wrapper per la stringa vecchio stile, nel caso in cui migliaia di URL aspettano che tu li aggiorni.
— Sławomir Lenart

Devi ancora importare anche altri pacchetti: import da django.conf.urls import url. Per favore aggiusta la tua soluzione.
— WebComer

1
@WebComer Non ho incluso l'importazione dell'URL nella domanda / risposta perché rimangono le stesse durante l'aggiornamento a Django 1.10 (a meno che tu non abbia django.conf.urls.defaultsDjango 1.5 o precedente). Ho aggiunto le importazioni come richiesto, ma non sono sicuro che questa sia una buona idea, poiché le importazioni cambiano di nuovo in Django 2.0. Se vuoi conoscere le importazioni corrette, i documenti per la tua versione di Django (ad esempio 1.11 , 2.0 ) sono il posto migliore dove cercare.
— Alasdair

3

Questo errore significa semplicemente che myapp.views.homenon è qualcosa che può essere chiamato, come una funzione. In effetti è una stringa. Anche se la tua soluzione funziona in django 1.9, tuttavia genera un avviso dicendo che questo sarà deprecato dalla versione 1.10 in poi, che è esattamente quello che è successo. La soluzione precedente di @Alasdair importa le funzioni di visualizzazione necessarie nello script tramite from myapp import views as myapp_views o from myapp.views import home, contact


1

Potresti anche ricevere questo errore se hai un conflitto di nomi di una vista e un modulo. Ho ricevuto l'errore quando distribuisco i miei file di visualizzazione nella cartella delle visualizzazioni /views/view1.py, /views/view2.pye ho importato un modello denominato table.py in view2.py che era il nome di una visualizzazione in view1.py. Quindi nominare la vista funziona come v_table(request,id) aiutato.


0

Il tuo codice è

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

modificalo in quanto segue mentre importi la include()funzione:

urlpatterns = [
    url(r'^$', views.home),
    url(r'^contact/$', views.contact),
    url(r'^login/$', views.login),
]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.