Django中的循环导入错误

时间:2018-08-12 20:32:27

标签: python django python-3.x

我组织了django结构,以包含一个views和urls文件夹。 在 / appfolder / urls / _ init _.py 或实际上在url中的任何位置导入 django.contrib.auth.views.login 时像这样查看文件夹:

from django.contrib.auth.views import login

我不断得到:

  

ImportError:无法导入名称登录

我认为这与更改后的结构有关。我想像这样将其包含在我的网址格式中:

path('portal/', login, {'template_name': 'portal/index.html'})

如何在不出现循环导入错误的情况下导入登录名?

目录结构

appfolder
│   
└─── __init__.py       
└─── admin.py
└─── apps.py   
└─── forms.py
└─── models.py         
│
└───urls
│   │   __init__.py     |
│   │   books_urls.py   |
|   |   movies_urls.py  |
|   |   portal_urls.py  |
│   |_ _ _ _ _ _ _ _ _ _|
|    
└───views
│   │   __init__.py      |
│   │   books_views.py   |
|   |   movies_views.py  |
|   |   portal_views.py  |
│   |_ _ _ _ _ _ _ _ _ _ |

appfolder / urls / _ init _.py

from django.urls import include
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf.urls.static import static
from django.conf import settings

from django.contrib.auth.views import login

from .books_urls import *
from .movies_urls import *
from .portal_urls import *

urlpatterns = [
    path('accounts/', include('django.contrib.auth.urls')),
    path('portal/', login, {'template_name': 'portal/index.html'}),
    path('portal/', include('appfolder.urls.portal_urls')),
    path('movies/', include('appfolder.urls.movies_urls')),
    path('books/', include('appfolder.urls.books_urls')),
]

urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Stacktrace:

> Unhandled exception in thread started by <function
> check_errors.<locals>.wrapper at 0x0000013AEBD7D048> Traceback (most
> recent call last):   File
> "C:\Users\User\Envs\webshop\lib\site-packages\django\utils\autoreload.py",
> line 225, in wrapper
>     fn(*args, **kwargs)   File "C:\Users\User\Envs\webshop\lib\site-packages\django\core\management\commands\runserver.py",
> line 117, in inner_run
>     self.check(display_num_errors=True)   File "C:\Users\User\Envs\webshop\lib\site-packages\django\core\management\base.py",
> line 379, in check
>     include_deployment_checks=include_deployment_checks,   File "C:\Users\User\Envs\webshop\lib\site-packages\django\core\management\base.py",
> line 366, in _run_checks
>     return checks.run_checks(**kwargs)   File "C:\Users\User\Envs\webshop\lib\site-packages\django\core\checks\registry.py",
> line 71, in run_checks
>     new_errors = check(app_configs=app_configs)   File "C:\Users\User\Envs\webshop\lib\site-packages\django\core\checks\urls.py",
> line 40, in check_url_namespaces_unique
>     all_namespaces = _load_all_namespaces(resolver)   File "C:\Users\User\Envs\webshop\lib\site-packages\django\core\checks\urls.py",
> line 57, in _load_all_namespaces
>     url_patterns = getattr(resolver, 'url_patterns', [])   File "C:\Users\User\Envs\webshop\lib\site-packages\django\utils\functional.py",
> line 37, in __get__
>     res = instance.__dict__[self.name] = self.func(instance)   File "C:\Users\User\Envs\webshop\lib\site-packages\django\urls\resolvers.py",
> line 533, in url_patterns
>     patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)   File
> "C:\Users\User\Envs\webshop\lib\site-packages\django\utils\functional.py",
> line 37, in __get__
>     res = instance.__dict__[self.name] = self.func(instance)   File "C:\Users\User\Envs\webshop\lib\site-packages\django\urls\resolvers.py",
> line 526, in urlconf_module
>     return import_module(self.urlconf_name)   File "C:\Users\User\Envs\webshop\lib\importlib\__init__.py", line 126, in
> import_module
>     return _bootstrap._gcd_import(name[level:], package, level)   File "<frozen importlib._bootstrap>", line 994, in _gcd_import   File
> "<frozen importlib._bootstrap>", line 971, in _find_and_load   File
> "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked 
> File "<frozen importlib._bootstrap>", line 665, in _load_unlocked  
> File "<frozen importlib._bootstrap_external>", line 678, in
> exec_module   File "<frozen importlib._bootstrap>", line 219, in
> _call_with_frames_removed   File "C:\Users\User\Desktop\project\company\com\com\urls.py", line 10, in
> <module>
>     path('', include('appfolder.urls')),   File "C:\Users\User\Envs\webshop\lib\site-packages\django\urls\conf.py",
> line 34, in include
>     urlconf_module = import_module(urlconf_module)   File "C:\Users\User\Envs\webshop\lib\importlib\__init__.py", line 126, in
> import_module
>     return _bootstrap._gcd_import(name[level:], package, level)   File "<frozen importlib._bootstrap>", line 994, in _gcd_import   File
> "<frozen importlib._bootstrap>", line 971, in _find_and_load   File
> "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked 
> File "<frozen importlib._bootstrap>", line 665, in _load_unlocked  
> File "<frozen importlib._bootstrap_external>", line 678, in
> exec_module   File "<frozen importlib._bootstrap>", line 219, in
> _call_with_frames_removed   File "C:\Users\User\Desktop\project\company\com\appfolder\urls\__init__.py",
> line 8, in <module>
>     from django.contrib.auth.views import login ImportError: cannot import name 'login'

1 个答案:

答案 0 :(得分:1)

您遇到的问题是,

from .portal_urls import *

仅从portal_urls.py中导入所有内容,这种导入是从当前文件目录中找到的,

import appfolder.urls.portal_urls

在加载appfolder/__init__.py之前将同时加载appfolder/urls/__init__.pyappfolder/urls/portal_urls.py([*]参见底部的示例)。

这就是为什么在您的appfolder/__init__.py中,编译器会超过此导入的原因

...
from .portal_urls import *

在窒息之前:

urlpatterns = [
    ...
    path('portal/', include('appfolder.urls.portal_urls')),

如果您以正常方式构建应用来避免此问题,即

appfolder
│   __init__.py
│   urls.py
│
├───books
│       __init__.py
│       urls.py
│
├───movies
│       __init__.py
│       urls.py
│
└───portal
        __init__.py
        urls.py

其中所有__init__.py个文件为空并且appfolder/urls.py包含

urlpatterns = [
    ...
    path(r'^portal/', include('appfolder.portal.urls')),
    path(r'^movies/', include('appfolder.movies.urls')),
    path(r'^books/', include('appfolder.books.urls')),

这种结构还使得将其中一个文件夹扩展到自己的模块中变得更加容易。

[*]如果将print(__file__)放在每个__init__.py文件中,则可以检查导入的内容:

(dev) go|c:\srv\tmp> python -c "import appfolder.books.urls"
appfolder\__init__.py
appfolder\books\__init__.py