URL Django TypeError: tampilan harus dapat dipanggil atau daftar / tupel dalam kasus termasuk ()

111

Setelah meningkatkan ke Django 1.10, saya mendapatkan kesalahan:

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

Urls.py saya adalah sebagai berikut:

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

Pelacakan lengkapnya adalah:

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
sumber
Jika kita menggunakan dekorator pada tampilan dan jika tidak mengembalikan apa pun. Dalam hal ini juga kami mendapatkan kesalahan di atas. baru-baru ini saya mendapat kesalahan ini.
anjaneyulubatta505
@AnjaneyuluBatta ya, jika dekorator tidak mengembalikan tampilan maka secara implisit mengembalikan None, yang akan menyebabkan TypeErrorseperti di atas.
Alasdair

Jawaban:

257

Django 1.10 tidak lagi memperbolehkan Anda untuk menetapkan tampilan sebagai string (mis. 'myapp.views.home') Dalam pola URL Anda.

Solusinya adalah memperbarui Anda urls.pyuntuk menyertakan tampilan yang dapat dipanggil. Ini berarti Anda harus mengimpor tampilan di file urls.py. Jika pola URL Anda tidak memiliki nama, maka sekarang adalah waktu yang tepat untuk menambahkannya, karena membalik dengan jalur python bertitik tidak lagi berfungsi.

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

Jika ada banyak tampilan, mengimpornya satu per satu bisa merepotkan. Alternatifnya adalah mengimpor modul views dari aplikasi Anda.

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

Perhatikan bahwa kami telah menggunakan as myapp_viewsdan as auth_views, yang memungkinkan kami untuk mengimpor views.pydari beberapa aplikasi tanpa bentrok.

Lihat dokumen dispatcher URL Django untuk informasi lebih lanjut tentang urlpatterns.

Alasdair
sumber
Bagaimana dengan tampilan berbasis kelas?
Rishabh Agrahari
2
Anda tidak pernah bisa menggunakan jalur string putus-putus untuk tampilan berbasis kelas, jadi itu tidak relevan dengan pertanyaan ini.
Alasdair
Saya ingin melihat perubahan seperti ini datang dengan beberapa helper (skrip migrasi), karena Anda tidak dapat menggunakan prefiks juga. import_moduledapat membantu Anda membuat pencarian sendiri sebagai pembungkus untuk string cara lama, jika ribuan url menunggu Anda untuk memperbaruinya.
Sławomir Lenart
Anda masih harus mengimpor paket lain juga - impor dari django.conf.urls import url. Harap perbaiki solusi Anda.
WebComer
1
@WebComer Saya tidak menyertakan impor url dalam pertanyaan / jawaban karena mereka tetap sama ketika meningkatkan ke Django 1.10 (kecuali Anda memiliki django.conf.urls.defaultsdari Django 1.5 atau sebelumnya). Saya telah menambahkan impor seperti yang Anda minta, tetapi saya tidak yakin bahwa ini ide yang bagus, karena impor berubah lagi di Django 2.0. Jika anda ingin mengetahui impor yang benar, maka dokumen untuk versi Django anda (misal 1.11 , 2.0 ) adalah tempat terbaik untuk melihatnya.
Alasdair
3

Kesalahan ini hanya berarti bahwa myapp.views.hometidak ada sesuatu yang bisa disebut, seperti fungsi. Faktanya itu adalah string. Meskipun solusi Anda bekerja pada django 1.9, namun ia mengeluarkan peringatan yang mengatakan ini akan berhenti dari versi 1.10 dan seterusnya, itulah yang sebenarnya telah terjadi. Solusi sebelumnya oleh @Alasdair mengimpor fungsi tampilan yang diperlukan ke dalam skrip melalui salah satu from myapp import views as myapp_views atau from myapp.views import home, contact

hAcKnRoCk
sumber
1

Anda mungkin juga mendapatkan kesalahan ini jika Anda memiliki nama benturan tampilan dan modul. Saya mendapat kesalahan saat mendistribusikan file tampilan saya di bawah folder views, /views/view1.py, /views/view2.pydan mengimpor beberapa model bernama table.py di view2.py yang kebetulan menjadi nama view di view1.py. Jadi penamaan fungsi tampilan sebagai v_table(request,id) membantu.

binboavetonik.dll
sumber
0

Kode Anda adalah

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

ubah menjadi mengikuti saat Anda mengimpor include()fungsi:

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