如何将所有的Django应用程序保存在特定文件夹中?

60

我有一个Django项目,假设它名为“project1”。 应用程序的典型文件夹结构如下:

/project1/
         /app1/
         /app2/
         ...
         __init__.py
         manage.py
         settings.py
         urls.py

如果我想把所有应用程序放在一个单独的文件夹中,比如叫做“apps”,应该怎么办?这样结构应该看起来像下面这样:

/project/
         apps/
              app1/
              app2/
              ...
         __init__.py
         manage.py
         settings.py
         urls.py
10个回答

65

您可以通过在 settings.py 中添加以下内容将apps文件夹添加到Python路径中:

import os
import sys

PROJECT_ROOT = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(PROJECT_ROOT, 'apps'))

那么你可以像在项目根目录中一样使用此文件夹中的所有应用程序!


10
如果你问我,这会导致混淆。 - Gabi Purcaru
7
当运行测试时,这会导致冲突。 - Ernest Jumbe
1
@ErnestJumbe 运行测试时会出现什么样的冲突?我使用这些方法并成功运行测试。 - run_the_race
这个能在 Django 3 上运行吗?当我运行服务器时,出现了 ModuleNotFoundError: No module named 'pages' 错误。pages 是其中一个应用程序的名称。 - R891
1
对于Django 3,这个答案有效:https://dev59.com/6m865IYBdhLWcg3wLbar#39747289 - R891

25

你可以很容易地做到这一点,但是你需要修改 settings.py,使其看起来像这样:

INSTALLED_APPS = (
    'apps.app1',
    'apps.app2',
    # ...
)

你的 urls.py 应该像这样:

urlpatterns = patterns('', 
    (r'^app1/',include('apps.app1')),    
    (r'^app2/',include('apps.app2')),    
)

..并修改任何import指向应用程序位置


4
我建议不要使用这种方法,因为它可能导致其他应用程序无法引用您自己的应用程序,并且需要更改应用程序中的所有导入以指向新目录。我认为正确的方法是参考Bernhard Vallant的答案 - sleblanc
这个相同的模式也被应用在 django-oscar 项目中。 - Dineshs91
我和sleblanc的想法一样,因为考虑到可重用模型的情况,你可能会使用例如ForeignKey('appname.ModelName', ...)来关联模型,所以对此感到不满。 - thclark
如果您计划在开发过程中使用这种约定,请注意您的迁移将在数据库中创建新表,并且不会映射到您正在处理的数据。 - Akarsh Jain

20

你可以利用 settings.py 中已存在的 BASE_DIR 变量。

只需添加以下内容:

import sys
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
希望这有所帮助。

1
BASE_DIR 不应该加引号吗? - run_the_race
是的,我的错。我会编辑答案。谢谢你指出来。 - anshuman
1
我认为这应该是Django 3的正确答案。 - R891

7
作为对Bernhard Vallant或Anshuman答案的轻微变体,这里有一个替代代码片段可放置在settings.py中。
import os
import sys  # Insert this line

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Insert the two lines below
APPS_DIR = os.path.join(BASE_DIR, '<your_project_dir_name>/apps/')
sys.path.insert(0, APPS_DIR)

以这种方式进行操作的额外好处是,您的模板目录更加干净整洁,因为它们将如下所示。如果没有APPS_DIR变量,则在TEMPLATES列表的DIRS列表中会有大量<your_project_dir_name>/apps/的重复。
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(APPS_DIR, '<app_name>/templates/<app_name>'),
            os.path.join(APPS_DIR, '<app_name>/templates/<app_name>'),
            ...
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

您可以按照正常方式列出 INSTALLED_APPS 列表中的应用程序,可使用在 apps.py 中给出的简短名称或使用长格式语法 appname.apps.AppnameConfig,将 appname 替换为您的应用程序名称。

3

很容易简单,您只需要将其添加到settings.py中即可。

import os
import sys

PROJECT_ROOT = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(PROJECT_ROOT, 'apps'))

并编辑您的应用程序配置,例如

旧的应用程序配置:

    class MyappConfig(AppConfig):
          default_auto_field = 'django.db.models.BigAutoField'
          name = 'myapp'

更新应用配置:

    class MyappConfig(AppConfig):
        default_auto_field = 'django.db.models.BigAutoField'
        label='myapp'
        name = 'apps.myapp'

与已安装的应用程序相比,例如:

INSTALLED_APPS = [
     ...
     'apps.myapp.apps.MyappConfig'
     ...
]

我认为这很有用并且能够提供帮助。祝你好运 :)


1

只需在您的应用程序文件夹中添加__init__.py(总共4个下划线)。现在,您可以执行以下操作

urlpatterns = [
        path('polls/',include('apps.polls.urls')),
        path('admin/', admin.site.urls)
]

1
如果您正在使用virtualenv/virtualenvwrapper(这有点过时但仍然有效),您可以使用包含的add2virtualenv命令来增强您的Python路径:
mkdir apps
cd apps
pwd
[/path/to/apps/dir]

将该路径复制到剪贴板,然后:
add2virtualenv /path/to/apps/dir

0
通过使用manage.py
# Fisrt create apps folder and appname subfolder
mkdir -p ./apps/<appname>

# Then create new app
python manage.py <appname> ./apps/<appname>

0
在我的情况下,我的项目文件夹结构如下:
/project/
   /apps/
      /app1/
      /app2/
   /src/
      /settings.py
      ...

所以我在我的settings.py文件中使用了这两行代码来解决它:

BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(BASE_DIR, '../apps'))

不需要修改 urls.py


0

以下方法适用于我。

这是文件夹结构:

/project1
    /apps
        /myapp

在/myapp下的apps.py文件中:

class MyAppConfig(AppConfig):
    name = "apps.myapp"

在settings.py文件中:
INSTALLED_APPS = [
    ...
    "apps.myapp.apps.MyAppConfig",
]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接