Django子目录视图及从__init__.py导入所有文件

3 投票
1 回答
3356 浏览
提问于 2025-04-16 06:14

从技术上讲,这不是一个关于Django的问题,更像是一个关于Python的问题。

在urls.py文件里,我有以下内容:

urlpatterns = patterns('locate.views',
    url(r'^',  'index.index'),
)

还有这样的目录结构:

locate/
  views/
    __init__.py
    index.py      #  where there is "def index(request) : ...."

我想要做的是,不想每次都说“index.index”,而是希望能让结构简单一些。这样就能得到:

urlpatterns = patterns('locate.views',
    url(r'^',  'index'),
)

当然,如果我在__ init __.py文件里写入以下内容,这是完全可以实现的:

from .index import index
...

但是在做了99次之后,能自动化这个过程就太好了。我尝试了一些__ import __之类的东西,已经接近了,但我想知道有没有其他人有可用的代码片段,或者有没有更好的方法来处理Django中的这种模式。

更新 使用了Amit代码的版本:

这段代码在views/__init__.py文件里(很快会被拉到一个库里):

from glob import glob1
from types import FunctionType
import os

def import_views(dirname, views_prefix='') :
    for filename in glob1(dirname, '*.py'):
        if filename == '__init__.py':    # I assume you don't want that
            continue

        module_name = os.path.basename(filename).split('.py')[0]

        # You might need to change this, depending on where you run the file:
        imported_module = __import__("%s.%s" % (__package__, module_name), fromlist=[module_name,])

        idict = imported_module.__dict__

        for method_name in idict.get('__all__', idict.keys()):
            method = idict[method_name]
            if not isinstance(method, FunctionType):
                continue
            if views_prefix and not method_name.startswith(views_prefix):
                continue
            globals()[method_name] = method

import_views(os.path.dirname(__file__))

1 个回答

2

我觉得通过其他文件导入有点麻烦,所有的视图应该直接导入,就像你现在做的那样。不过,你可以创建一个 views.py 文件,把所有相关的视图方法从那里导入,目录结构保持不变,只需要在 views/ 目录下添加一个 views.py 文件。这个文件里的代码应该像这样:

from .index import index
from .other_view import other_view_method
...

然后在你的 urls.py 文件中的代码会变成:

 urlpatterns = patterns('locate.views',
    url(r'^',  'index.index'), )

变成这样:

urlpatterns = patterns('locate.views.views',
    url(r'^',  'index'),
)

不过,如果你还是想遍历所有的 *.py 文件并从中获取所有视图方法,你可以创建一个加载器文件,先运行这个文件来加载所有视图,代码应该像这样:

from glob import glob1
from types import FunctionType

VIEW_METHOD_PREFIX = ''    # Whatever you like here, I suggest you use something
VIEWS_DIR          = 'views'    # Where you views are

def import_views():

    for filename in glob1(VIEWS_DIR, '*.py'):
        if filename == '__init__.py':    # I assume you don't want that
            continue

        module_name = os.path.basename(filename).split('.py')[0]

        # You might need to change this, depending on where you run the file:
        imported_module = __import__(
            module_name, fromlist=[module_name,])  

        for method_name, method in imported_module.__dict__.iteritems():
            if not isinstance(method, FunctionType):
                continue
            if not method_name.startswith(VIEW_METHOD_PREFIX):
                continue
            globals()[method_name] = method

然后在 urls.py 中你添加:

import_views()

撰写回答