2012-01-30 143 views
2

我正在使用Django,我喜欢将我的模型,视图和测试分离到子目录中。在Python中实现“from。import *”的最佳方式是什么?

但是,这意味着我需要在导入该目录中每个模块的每个子目录中保留一个__init__.py

我宁愿只是把一些呼叫,说:

from some_library import import_everything 
import_everything() 

这将对作为遍历当前目录相同的效果,并在该目录中导入所有的.py文件。

什么是最好/最简单的方法来实现这个?

这里是什么我的Django应用程序目录(基本)的样子:

some_django_app/ 
    models/ 
     __init__.py 
     create.py 
     read.py 
     update.py 
     delete.py 
    views/ 
     __init__.py 
     create.py 
     read.py 
     update.py 
     delete.py 
    forms/ 
     __init__.py 
     create.py 
     update.py 
    tests/ 
     __init__.py 
     create.py 
     read.py 
     update.py 
     delete.py 

所以,你可以看到,做一个“适当”的Django应用程序,我所有的初始化 .py文件需进口每个目录中的所有其他.py文件。我宁愿在那里有一些简单的样板。

+0

您可以添加示例目录布局吗? – Cameron 2012-01-30 18:49:39

+0

更新为包含目录布局。 – slacy 2012-01-30 19:01:56

+0

请注意'来自。 import *'通常是一个坏主意,因为名字空间可能会在您不知情的情况下被覆盖。请参阅[有关该主题的文档](http://docs.python.org/howto/doanddont.html#from-module-import) – 2012-01-30 19:42:31

回答

1

使用synthesizerpatel's answer给出的信息,你可以实现import_everything这样:

import os 
import sys 

def import_everything(path): 
    # Insert near the beginning so path will be the item removed with sys.path.remove(path) below 
    # (The case when sys.path[0] == path works fine too). 
    # Do not insert at index 0 since sys.path[0] may have a special meaning 
    sys.path.insert(1,path) 
    for filename in os.listdir(path): 
     if filename.endswith('.py'): 
      modname = filename.replace('.py', '') 
      module = __import__(modname, fromlist = [True]) 
      attrs = getattr(module, '__all__', 
          (attr for attr in dir(module) if not attr.startswith('_'))) 
      for attr in attrs: 
       # print('Adding {a}'.format(a = attr)) 
       globals()[attr] = getattr(module, attr) 
    sys.path.remove(path) 

,并且可以使用这样的:

print(globals().keys()) 
# ['import_everything', '__builtins__', '__file__', '__package__', 'sys', '__name__', 'os', '__doc__'] 

import_everything(os.path.expanduser('~/test')) 

print(globals().keys()) 
# ['hashlib', 'pythonrc', 'import_everything', '__builtins__', 'get_input', '__file__', '__package__', 'sys', 'mp', 'time', 'home', '__name__', 'main', 'os', '__doc__', 'user'] 
4

在您app/models/__init__.py加上这些行:

from app.models.create import * 
    from app.models.read import * 
    from app.models.update import * 
    from app.models.delete import * 

这将是您最好的选择简洁和可读性。 from app.models import *现在将加载其他每个文件中的所有类/ etc。同样,from app.models import foo将加载foo,无论它定义在哪个文件中。

+0

是的,这正是我现在所做的,我觉得它很累。对于每个新的测试用例或表单,我都需要不断更新__init__.py。对于大多数情况(模型,视图),这是可以的,但是对于测试来说这是最糟糕的,因为我喜欢在那里有很多文件,而不是一个巨大的tests.py,__init__.py在其中有很多行。 – slacy 2012-01-30 20:10:27

+0

@slacy这听起来像是一种糟糕的组织方式。为什么不把测试分成逻辑分组 - model_tests.py,view_tests.py等等? (或其他一些对该应用有意义的分组,例如user_tests,guest_tests或其他) – Izkata 2012-01-30 21:04:34

+0

是的,实际上,我们确实有model_tests.py和view_tests,但即使是那些文件也会得到> 1000行,我们最终将它们分开。 :) – slacy 2012-01-30 22:28:55

相关问题