[Django]-Django serving each app separately in each its port

13👍

This is possible, but not the way you’re conceptualizing it. A Django app is one part of what runs on a given web server. Thus a Django project, which has one or more apps, runs as a part of one web server.

The solution is to run multiple instances of Django. Not sure how well this is going to work for you with the debug servers. You can run each server on its own port by giving it a parameter telling it where to open the port, for example:

./manage.py runserver 8000

runs a debug server on 127.0.0.1:8000, and

./manage.py runserver 8080

runs another debug server on 127.0.0.1:8080. Usually this is done in separate shells.

You will need to make sure that the INSTALLED_APPS setting on one of these has 'Ebony' in it, and the other has 'Ivory'. You will also need to figure out some way to tell each instance how to connect to the other (usually by specifying a root URL).


That said, later on you will need to figure out if your two apps will be sharing the same database. If so, make sure that both machines can get to it. If not, make sure the DATABASES value in settings.py is different for each one. If you’re sharing the database, Django’s sites framework can help you keep things straight in your models.


To have both running from the same project, you have to tell Django which one to run. I prefer to use an environment variable. This changes the above runserver commands to:

SHARD=Ebony ./manage.py runserver 8000

and

SHARD=Ivory ./manage.py runserver 8080

In your settings.py file, this variable can be accessed through os.environ. So, for example, for the INSTALLED_APPS setting to have different values for each shard, you write something like:

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

By defining SHARD as a setting in this file, you avoid having to have all your code access the environment variable, and you confine the logic for setting SHARD to settings.py, in case you want to change it later. Your other Python files, if needed, can get the setting with from django.conf.settings import SHARD.

A similar mechanism can be used to give each shard its own DATABASES setting, too. And anything else in settings.py.

Then later in your urls.py file, you use that to pull in your apps’ URLs:

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)),
    )

This means your apps need their own urls.py files, and your app URL names get prefixed with your app names. So if the app Ebony defines a URL pattern with name="index", you would get that URL in a template with {% url 'Ebony:index' %}.

0👍

For anyone willing to have multiple servers or ports for the same Django app, but is actually just trying to implement a monolitic project hosting both backend and frontend for your project, a very simple solution is to add prefixes to each "server", or just add a prefix for backend endpoints, like /api/.

Example:

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"),
]

Leave a comment