17

我是 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 ... 异常值:“模块”对象没有属性“搜索”

我认为正在发生的事情是,由于最后导入了来自联系人的视图,Django 正在查看不包含搜索的联系人视图(搜索在书籍视图中)。

从 Django urls 文件中的两个不同应用程序导入 views.py 文件的正确方法是什么?

谢谢你的帮助!

4

5 回答 5

21

免责声明:不是 Django 答案

问题在于这两行:

from books import views
from contact import views

第二个导入遮住了第一个,因此当您views稍后使用时,您只使用viewsfrom 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
于 2012-07-11T18:56:03.093 回答
11
from books import views
from contact import views

您正在覆盖 name views。您需要将它们作为不同的名称或绝对名称导入。

import books.views
import contact.views

... 或者 ...

from books import views as books_views
from contact import views as contact_views

然后在定义 URL 时使用正确的名称。(books.views.searchbooks_views.search取决于您选择的方法)

于 2012-07-11T18:56:49.190 回答
4

我回答这个问题的原因是因为它是多年前回答的,而这些答案对于较新的 Django 版本不再正确或有用,或者您应该了解更好的做法。

因此,如果您的 Django 项目中有多个应用程序,那么您应该为每个应用程序使用一个新的 urls.py 文件。这意味着如果您启动一个新应用程序,那么您必须在新应用程序的子文件夹中手动创建一个名为 urls.py 的新文件。许多初学者首先不明白为什么这样做很好,但如果您计划在一个 Django 项目中创建更多应用程序,这是一个很好的做法。

当您启动一个项目时,会在您的项目文件夹中自动创建 urls.py 文件,但是如果您在 Django 中创建/启动一个新应用程序,那么最好为该应用程序自己创建一个单独的 urls.py文件夹。(这样一来,您将永远不会遇到“将不同应用程序的视图导入 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”方法,然后您可以将 my_new_app urls.py 文件包含在项目的主 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 提供任何 url。)

现在,您可以在 Django 项目中创建另一个名为 my_second_app 的应用程序,您也应该为该应用程序重复上述步骤。这样,您将来自不同应用程序的视图导入 urls.py 文件不会有任何问题。对于 2017 年 Django 1.11 中的这个问题,这将是一个非常基本的“良好实践解决方案”。

于 2017-08-10T09:06:25.420 回答
2

URLconfs 文档给出了相同情况的示例

您可以跳过导入并按应用程序分隔网址,如下所示:

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
)
于 2012-07-11T19:28:18.447 回答
0

这是我针对不同视图/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()),
]
于 2020-10-16T02:30:14.993 回答