django deploying separate web & api endpoints on heroku
Asked Answered
D

2

9

I have a web application with an associated API and database.

I'd like to use the same Django models in the API, but have it served separately by different processes so I can scale it independently.

I also don't need the API to serve static assets, or any of the other views.

The complication is that the routes I have defined have the API and the webapp sharing the root domain:

http://domain.com/normal/application/stuff
http://domain.com/api/different/stuff

and additionally my Django apps depend on each other's models and constants (so two different settings.py files with different INSTALLED_APPS doesn't quite solve it).

I guess one way is I could define different processes in my Procfile which just start the Django app, but that in one of the processes it might have different environment variables? I don't think I can change the environment per Proc with heroku:config, I think it would actually have to be a directive in the Procfile.

Anyone have any experience or insight with this? Thanks!

Dictum answered 2/7, 2015 at 16:49 Comment(4)
FWIW, the bigger problem with what you want to do isn't how to configure Django, it is the fact that you want to do both under the same domain name. This means you cannot split the segmented applications across separate web dynos if you wanted to be able to scale them separately at the level of a dyno. Some WSGI servers do provide enough configuration ability to segment a web application within the one host, and specify different number of processes/threads for different parts of the application, but the gunicorn WSGI server that Heroku recommends isn't one of them.Maltz
could I still use a single Django application / Heroku application but have a settings.py for a domain and one for a subdomain?Dictum
You could do it if you were using Apache/mod_wsgi as the WSGI server, but Heroku setup doesn't allow that to be run with Python 2.7. Can only use it with Python 3.3+ and then it still requires some tricks on the part of mod_wsgi to enable it to be installed on Heroku. Unfortunately can't guarantee that Heroku will not change things so doesn't work on Python 3.3+ as well.Maltz
OK, great. I think you have the most correct assessment of the situation. Thanks!Dictum
F
2

As Daniel said you could just use two settings files, with a shared base. If you want to serve a subset of the urls you should just also create separate url definitions in the ROOT_URLCONF setting.

So your project structure would be something like this:

project/
    project/
       settings/
           __init__.py
           base.py
           normal.py
           api.py
       urls/
           __init__.py
           base.py
           normal.py
           api.py
       wsgi/
           __init__.py
           normal.py
           api.py

settings/normal.py (analog for api) would be somthing like this:

from .base import *
ROOT_URLCONF = 'project.urls.normal
Factitious answered 11/7, 2015 at 8:45 Comment(4)
This seems like it would solve the problem. Are there any disadvantages to doing this over, say, splitting the app into one (normal) serving a domain and the other (api) serving a subdomain?Dictum
Not that I could think ofFactitious
wait - if a request comes in how does gunicorn know which process to serve to? will both processes check their urls.py? I'm not seeing a way it could tell the difference.Dictum
this won't actually work with a shared domain, but it is probably the best answer. see Graham's answer for the most correct assessment of the situationDictum
S
1

I don't think you need different environment variables, just a separate WSGI file pointing to a different settings.py. Those settings file can import shared settings from a common file, then set their particular values for INSTALLED_APPS. Then the Procfile can refer to those wsgi files in separate processes.

Souvenir answered 2/7, 2015 at 16:57 Comment(1)
Two wsgi files and two settings files would work. However, if there is any dependency between apps (so unable to remove apps from INSTALLED_APPS), it would still serve through urls.py all the different endpoints, yes?Dictum

© 2022 - 2024 — McMap. All rights reserved.