我是Django的新手,并通过Holovaty和Kaplan-Moss的“The Django Book”工作。我有一个名为“mysite”的项目,其中包含两个名为“books”和“contact”的应用程序。每个都有自己的view.py文件。在我的urls.py文件中,我有以下内容:
from books import views
from contact import views
...
urlpatterns = patterns('',
...
(r'^search/$', views.search),
(r'^contact/$', views.contact),
...
当我运行我的代码时,我收到此错误:
/ search /中的NameError ... 异常值:'module'对象没有属性'search'
我认为正在发生的事情是,由于联系人的观点是最后导入的,因此Django正在查看不包含搜索的联系人视图(搜索在书籍视图中)。
从Django urls文件中的两个不同应用程序导入views.py文件的正确方法是什么?
感谢您的帮助!
答案 0 :(得分:18)
免责声明:不是Django的回答
问题在于这两行:
from books import views
from contact import views
第二个导入是第一个导入,因此当您稍后使用views
时,您只使用views
中的contact
。
一种解决方案可能就是:
import books
import contact
urlpatterns = patterns('',
...
(r'^search/$', books.views.search),
(r'^contact/$', contact.views.contact),
...
我不确定,但我也认为你实际上并不需要导入任何东西,只能在你的模式中使用字符串,例如:'books.views.search'
。
另一种可能性是遵循Simon Visser建议:
from books.views import search
from contact.views import contact
答案 1 :(得分:6)
from books import views
from contact import views
您正在覆盖名称views
。您需要将它们作为不同的名称或绝对名称导入。
import books.views
import contact.views
......或......
from books import views as books_views
from contact import views as contact_views
然后在定义网址时使用正确的名称。 (books.views.search
或books_views.search
取决于您选择的方法)
答案 2 :(得分:2)
URLconfs documentation给出了相同情况的示例
您可以跳过导入并按app分隔网址:
urlpatterns = patterns('books.views',
(r'^/book/search/$', 'search'), #calls books.views.search
)
urlpatterns += patterns('contact.views', #make note of the '+='
(r'^/contact/search/$', 'search'), #calls contact.views.search
)
答案 3 :(得分:1)
我回答这个问题的原因是因为它在几年前得到了解答,而且对于较新的Django版本,这些答案不再正确或有用,或者你应该知道更好的做法。
因此,如果您的Django项目中有多个应用程序,那么您应该为每个应用程序使用新的urls.py文件。这意味着如果您启动一个新应用程序,则必须在新应用程序的子文件夹中手动创建一个名为urls.py的新文件。许多初学者首先不明白为什么这是好的,但如果您计划在一个Django项目中创建更多应用程序,这是一个很好的做法。
当你启动一个项目时,urls.py文件会自动在你的项目文件夹中创建,但如果你在Django中创建/启动一个新应用程序,那么如果你为该应用程序创建一个单独的urls.py是一个很好的做法。在自己的文件夹中。 (通过这种方式,您将永远不会有#34;首先将不同应用的视图导入urls.py"问题。)
为您的应用创建urls.py文件后,您必须以下列方式在项目的urls.py文件中包含该应用的urls.py文件:
让我们看一下创建名为“my_new_app”的新应用时的示例。 这是项目的主要urls.py文件的样子:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^my_new_app/', include('my_new_app.urls')),
]
在项目的urls.py文件中,您必须导入'include'方法,然后您可以在项目的主urls.py文件中包含my_new_app urls.py文件。在my_new_app文件夹中,您必须手动创建urls.py文件,如上所述。然后你必须将该文件用于my_new_app的所有urlpatterns。然后当然这样它将自动包含在项目的主urls.py文件中。
那么这就是你的my_new_app自己的urls.py文件的样子:
from django.conf.urls import url
from my_new_app import views
urlpatterns = [
url(r'^$', views.index, name = "index"),
]
假设您还在'my_new_app / views.py文件中创建了名为'index'的第一个视图。
my_new_app / views.py文件如下所示:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello World!")
您可以在浏览器中查看my_new_app:
http://localhost:8000/my_new_app
(当然,您可以在项目的urls.py文件中为my_new_app提供任何网址。)
现在,您可以在Django项目中创建另一个名为my_second_app的应用程序,您也应该为该应用程序重复上述步骤。这样,将不同应用程序中的视图导入urls.py文件就不会有任何问题。对于2017年Django 1.11中的这个问题,这将是一个非常基本的“良好实践解决方案”。
答案 4 :(得分:0)
在这里,我针对不同的View / API版本采用的方法:
from django.urls import path
from my_app import views as api_v1
from my_app import views_v2 as api_v2
urlpatterns = [
path('view_one', api_v1.ViewOne.as_view()),
path('view_two', api_v2.ViewTwo.as_view()),
]