Django在不同端口分别服务每个应用
我有一个非常简单的项目在用Django(还没有模型),我需要做以下事情:
我创建了两个应用,'Ebony'
和'Ivory'
,它们需要通过JSON
消息互相通信(最初是设计成可以在不同的机器上运行,但现在在同一台机器上就可以了)。
问题是,Django的Debug
服务器只有一个进程,它在一个特定的端口上运行。我想让每个'App'
在同一台服务器上监听自己的端口,如果可以的话,还希望在同一个Django项目下。这样的情况可能吗?如果可以,我该怎么做呢?
提前谢谢你!
2 个回答
如果你想在同一个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"),
]
这是可以实现的,但不是你想的那样。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。