Django在不同端口分别服务每个应用

3 投票
2 回答
4869 浏览
提问于 2025-04-18 04:28

我有一个非常简单的项目在用Django(还没有模型),我需要做以下事情:

我创建了两个应用,'Ebony''Ivory',它们需要通过JSON消息互相通信(最初是设计成可以在不同的机器上运行,但现在在同一台机器上就可以了)。

问题是,Django的Debug服务器只有一个进程,它在一个特定的端口上运行。我想让每个'App'在同一台服务器上监听自己的端口,如果可以的话,还希望在同一个Django项目下。这样的情况可能吗?如果可以,我该怎么做呢?

提前谢谢你!

2 个回答

0

如果你想在同一个Django应用上使用多个服务器或端口,但其实只是想把项目的后端和前端放在一起,一个很简单的办法就是给每个“服务器”加上前缀,或者只给后端的接口加个前缀,比如 /api/

举个例子:

urls.py

import myproject.apps.website.views.example_view as example_view
import myproject.apps.apis.v1.example_view as api_example_view
import myproject.apps.apis.v1.example_view_2 as api_example_view_2


urlpatterns = [
    path("admin/", admin.site.urls, name="admin"),
    ...
    # Docs
    path("iapi/doc/schema/", SpectacularAPIView.as_view(), name="schema"),
    ...
    # Backend
    path("api/be_page/", api_example_view.get, name="some_be_view"),
    path("api/be_page_2/<str:id>/", api_example_view_2.edit, name="some_be_view_2_edit"),
    # Frontend
    path("", example_view.get, name="root_fe_view"),
    path("fe_page/list", example_view.get, name="some_fe_view_list"),
    path("fe_page/edit/<str:id>/", example_view.edit, name="some_fe_view_edit"),
]
14

这是可以实现的,但不是你想的那样。Django应用程序是运行在某个网络服务器上的一部分。因此,一个Django项目可以包含一个或多个应用,它们作为一个整体在一个网络服务器上运行。

解决方案是运行多个Django实例。不太确定在调试服务器上这样做效果如何。你可以通过给服务器一个参数来指定它在哪个端口上运行,每个服务器可以在自己的端口上运行,例如:

./manage.py runserver 8000

在127.0.0.1:8000上运行一个调试服务器,而

./manage.py runserver 8080

在127.0.0.1:8080上运行另一个调试服务器。通常,这些是在不同的命令行窗口中运行的。

你需要确保其中一个实例的INSTALLED_APPS设置中包含'Ebony',而另一个实例中包含'Ivory'。你还需要找出一种方法,让每个实例知道如何连接到另一个实例(通常是通过指定一个根URL)。


说到这里,稍后你需要确定这两个应用是否会共享同一个数据库。如果是的话,确保两个实例都能访问这个数据库。如果不是,确保在settings.py中的DATABASES值是不同的。如果你们共享数据库,Django的站点框架可以帮助你在模型中保持清晰。


要让两个应用从同一个项目中运行,你需要告诉Django运行哪个应用。我更喜欢使用环境变量。这样,上面的runserver命令就变成了:

SHARD=Ebony ./manage.py runserver 8000

SHARD=Ivory ./manage.py runserver 8080

在你的settings.py文件中,这个变量可以通过os.environ访问。例如,为了让INSTALLED_APPS设置在每个实例中有不同的值,你可以写类似这样的代码:

SHARD = os.environ["SHARD"]

# Apps common to all shards go here.
LOCAL_APPS = [
    commonApp,
]

# Add apps specific to each shard.
if SHARD == "Ebony":
    LOCAL_APPS += [
        Ebony,
    ]
elif SHARD == "Ivory":
    LOCAL_APPS += [
        Ivory,
    ]

# Add them to the apps that aren't mine.
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.admin',
    # ... omitted for brevity ...
    'django_extensions',
    'south',
    'debug_toolbar',
) + LOCAL_APPS

通过在这个文件中定义SHARD作为一个设置,你可以避免所有代码都去访问环境变量,并且将设置SHARD的逻辑限制在settings.py中,以便将来如果需要更改时更方便。如果需要,你的其他Python文件可以通过from django.conf.settings import SHARD来获取这个设置。

类似的机制也可以用来给每个实例设置自己的DATABASES设置,以及settings.py中的其他任何内容。

然后在你的urls.py文件中,你可以用这个来引入你应用的URL:

from django.conf.urls import *
from django.conf import settings
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$', 'commonApp.views.get_homepage', name='home'),
    url(r'^login$', 'django.contrib.auth.views.login', name="login"),
    url(r'^logout$', 'django.contrib.auth.views.logout', 
        {"next_page": "/"}, name="logout"),
# Admin
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    url(r'^admin/', include(admin.site.urls)),
)

# Auto-add the applications.
for app in settings.LOCAL_APPS:
    urlpatterns += patterns('',
        url(r'^{0}/'.format(app), include(app + '.urls', namespace=app)),
    )

这意味着你的应用需要有自己的urls.py文件,并且你的应用URL名称会以应用名称为前缀。所以如果应用Ebony定义了一个URL模式,名称为"index",你可以在模板中用{% url 'Ebony:index' %}来获取这个URL。

撰写回答