6

我在 Django 中的文件夹结构如下:

./project_root
    ./app
       ./fixtures/
       ./static/
       ./templates/
       ./blog/
       ./settings.py
       ./urls.py
       ./views.py
       ./manage.py
       ./__init__.py 
    ./plugin
       ./code_editor
           ./static
           ./templates
           ./urls.py
           ./views.py
           ./__init__.py 
       ./code_viewer
           ./static
           ./templates
           ./urls.py
           ./views.py
           ./__init__.py 

那么,如何让根 urls.py 根据 INSTALLED_APPS 通过查找其他 urls.py 来自动构建 url 列表?我更改了 settings.py 以动态构建 INSTALLED_APPS、TEMPLATES_DIR、STATICFILES_DIRS。(这意味着我不知道在不同的服务器上会安装多少插件。它应该在运行时动态检查并添加它。)on:

python manage.py runserver

这是添加 INSTALLED_APPS、TEMPATS_DIR、STATICFILES_DIR 的代码。

PLUGINS_DIR = '/path_to/plugins/'

for item in os.listdir(PLUGINS_DIR):
    if os.path.isdir(os.path.join(PLUGINS_DIR, item)):
        plugin_name = 'app.plugins.%s' % item

    if plugin_name not in INSTALLED_APPS:
        INSTALLED_APPS = INSTALLED_APPS+(plugin_name,)

    template_dir = os.path.join(PLUGINS_DIR, '%s/templates/' % item)

    if os.path.isdir(template_dir):
        if template_dir not in TEMPLATE_DIRS:
            TEMPLATE_DIRS = TEMPLATE_DIRS+(template_dir,)

    static_files_dir = os.path.join(PLUGINS_DIR, '%s/static/' % item)

    if os.path.isdir(static_files_dir):
        if static_files_dir not in STATICFILES_DIRS:
            STATICFILES_DIRS = STATICFILES_DIRS + (static_files_dir,)

任何帮助将不胜感激。先感谢您。

解决方案:

编辑:所以我所做的如下:

我包括两个这样的模块:

from django.conf import settings
    from django.utils.importlib import import_module

然后在根 urls.py 中添加以下代码:

def prettify(app):
    return app.rsplit('.', 1)[1]


for app in INSTALLED_APPS:

    try:
        _module = import_module('%s.urls' % app)
    except:
        pass
    else:
        if 'eats.plugins' in app:
            urlpatterns += patterns('',
                                    url(r'^plugins/%s/' % prettify(app), include('%s.urls' % app))
                                    )

非常感谢@Yuka。谢谢你。谢谢你。谢谢你。谢谢你.... 你让我开心。

4

5 回答 5

6

你想要的是这样的:

from django.utils.importlib import import_module
for app in settings.INSTALLED_APPS:

    try:
        mod = import_module('%s.urls' % app)
        # possibly cleanup the after the imported module?
        #  might fuss up the `include(...)` or leave a polluted namespace
    except:
        # cleanup after module import if fails,
        #  maybe you can let the `include(...)` report failures
        pass
    else:
        urlpatterns += patterns('',
            url(r'^%s/' % slugify(app), include('%s.urls' % app)
        )

您还想slugify从 django 模板或实用程序中窃取并实现自己的(我不确定这些天它在哪里?)并稍微修改它以去除您不想要的任何“点”和其他无用的命名空间在您的“网址”中,例如您可能不希望您的网址看起来像这样:“example.com/plugin.some_plugin_appname/”但喜欢example.com/nice_looking_appname/

您甚至可能根本不希望它自动命名,而是在您的插件自己的“设置”模块中创建一个可配置的“设置”或类似的东西:

# plugin settings conf
url_namespace = 'my_nice_plugin_url/'

# root urls.py:
url(r'^%s/' % mod.url_namespace, include(...))
# or:
url(r'^%s/' % app.settings.url_namespace, inc..

你可能明白了它的要点。

亲切的问候,

于 2013-11-07T13:34:12.813 回答
1

我修改了@wdh 的逻辑,并使用 Django 2.2.9(2020 年 1 月最新稳定版)和 python 3.8 进行了测试

网址.py

from django.apps import apps
from django.conf import settings

for app in settings.INSTALLED_APPS:
    if app.startswith('myappsprefix_'):
        app_config = apps.get_app_config(app.rsplit('.')[0])
        urlpatterns += i18n_patterns(
            path(f'{app_config.urls}/', include(f'{app_config.name}.urls')),
        )

i18n_patterns是为了国际化。

每个应用程序的apps.py

class MyCustomAppsConfig(AppConfig):
    name = 'myappsprefix_mycustomapp'
    urls = 'mybaseurlforapp'  # required!

在我的 settings.py

INSTALLED_APPS = [
    ...

    'myappsprefix_mycustomapp.apps.MyCustomAppsConfig',
    ...
]
于 2020-01-27T15:47:38.653 回答
1

最好不要按照django 文档INSTALLED_APPS中的说明直接访问,而是使用注册表:

from django.apps import apps

for app in apps.get_app_configs():
    app_name = app.name
    try:
        ...
于 2020-03-06T21:19:49.273 回答
0

您是否尝试过类似的方法:

for app in INSTALLED_APPS:

    # You'll want to check that you can import the urls of that app here

    urlpatterns += patterns('',
        url(r'^%s/' % app, include('%s.urls' % app) )
    )
于 2013-11-07T13:06:26.973 回答
0

我进一步修改了@Progressify 的代码以取消应用前缀。

# in your project's urls.py
from django.apps import apps
from django.contrib import admin
from django.conf import settings
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    # ...
    # any other paths you may have
]

# Load urls from any app that defines a urls attribute in appname.apps.AppConfig
for app in settings.INSTALLED_APPS:
    try:
        app_config = apps.get_app_config(app.rsplit('.')[0])
        try:
            urls = app_config.urls
            urlpatterns += [
                path(f'{app_config.urls}', include(f'{app_config.name}.urls', namespace=f'{app_config.urls_namespace}')),
            ]
        except AttributeError:
            pass
            
    except LookupError:
        pass

这将在项目的 apps.py 中查找定义前缀和命名空间的 AppConfig,并相应地包含它们。诚然,错误捕获有点粗糙,因此您可能需要根据您是否要允许您的应用程序定义 url 而不是命名空间等来对其进行一些细化。

# in each of your apps' apps.py
from django.apps import AppConfig

class UsersConfig(AppConfig): # name the class whatever you want
    name = 'users'            # name of your app
    urls = ''                 # prefix for this app's urls –– may need to append slash
    urls_namespace = 'users'  # app url namespace –– it's "best practice" to define one
于 2020-07-28T15:41:14.057 回答