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.