How does Django manage different subdomains on one Django project? - django

I want my Django project to be accessible at many different endpoints. For one app, I want it accessible at app.domain.com and for another app I want it accessible at dashboard.domain.com. How can I achieve this? I am using AWS Elastic Beanstalk and Route 53.
I tried looking at Django's djangoproject.com and their Github repo, as they do this. However, I couldn't figure it out. Thanks!

You can define two settings.py file, with two associated urls.py files :
app_settings.py
from my_project.settings import *
ROOT_URLCONF = 'my_project.app_urls'
ALLOWED_HOSTS = ['app.domain.com']
dashboard_settings.py
from my_project.settings import *
ROOT_URLCONF = 'my_project.dashboard_urls'
ALLOWED_HOSTS = ['dashboard.domain.com']
Define your urls for each website respectively in my_project/app_urls.py and my_project/dashboard_urls.py
Then start two instances of your django project (with uwsgi, gunicorn ou whatever you use) with those two distinct settings files (using DJANGO_SETTINGS_MODULE environment variable for example).
This way, both instances shares the same codebase but exposes distinct urls.
For example, using uwsgi, you could have those two files (with distinct ports) :
app.ini
[uwsgi]
http = 127.0.0.1:8001
module = my_project.wsgi
processes = 4
threads = 2
pidfile = app.pid
env = DJANGO_SETTINGS_MODULE=my_project.app_settings
dashboard.ini
[uwsgi]
http = 127.0.0.1:8002
module = my_project.wsgi
processes = 4
threads = 2
pidfile = app.pid
env = DJANGO_SETTINGS_MODULE=my_project.dashboard_settings

Related

uwsgi emperor share and use a common default ini within projects

I'm using the uwsgi Emperor to manage multiple Flask apps, and for each individual app, I have several ini configs, e.g. local.ini, production.ini that I want to share common ini features from a central default.ini. And I'd like be able to do this for multiple projects, i.e. different projects can have different defaults. However, I cannot get the emperor to follow the symlinks to recognize the default.ini file. How do I get the emperor to follow symlinks so each project can understand its default.ini location? I always get the error
realpath() of default.ini failed: No such file or directory
emperor.ini setup file
[uwsgi]
emperor = /www/uwsgi/vassals
emperor-broodlord = 40
logto = /www/uwsgi/log/emperor.log
master = true
thunder-lock = true
enable-threads = true
stats = /tmp/empstats.sock
die-on-term = true
My vassals directory is set up with symlinks that point to the respective projects ini files
uwsgi_app1.ini -> /path/to/project1/local.ini
uwsgi_app2.ini -> /path/to/project2/local.ini
For each separate project, I have a default.ini which contains common settings I want to use for both local and production environments, for that project.
Project1
default.ini
[uwsgi]
file = %(wwwdir)/%(module)/run_%(app_name)
daemonize = %(wwwdir)/%(module)/log/%(app_name).log
socket = %(socketdir)/uwsgi_%(app_name).sock
stats = %(socketdir)/%(module)_stats.sock
master = true
processes = 4
chmod-socket = 666
vacuum = true
thunder-lock = true
enable-threads = true
lazy-apps = true
with local.ini and production.ini, having slightly different variables, being
local
[uwsgi]
callable = app
wwwdir = /localwww/
socketdir = /tmp
module = app1
app_name = app1
ini = default.ini
production
[uwsgi]
callable = app
wwwdir = /home/var-www/
socketdir = /run/uwsgi/tmp
module = app1
app_name = app1
ini = default.ini
If I use the %p magic variable to specify the absolute path, it instead points to the emperor vassal directory www/uwsgi/vassals/default.ini, rather than the real path.
I am using a full path to the default.ini in the project file...
ini = /path/to/my/project/config/uwsgi/defaults.ini

django set multiple allowed hosts

I'm trying to set multiple allowed hosts in django
I have setting configured in production settings production.py as
ALLOWED_HOSTS = env('DJANGO_ALLOWED_HOSTS')
which I can then set on heroku with:
heroku config:set 'DJANGO_ALLOWED_HOSTS' = 'www.example.com'
However how can I add multiple hosts via this method?
You can provide a delimiter then split the string in django
ALLOWED_HOSTS = env('DJANGO_ALLOWED_HOSTS').split(',')
heroku config:set 'DJANGO_ALLOWED_HOSTS' = 'www.example.com,foo.com'
To define multiple values for allowed hosts in settings.py file use like:
ALLOWED_HOSTS = ['000.08.10.11','111.22.33.44','www.abcdefgh.com']

Why is python-pdfkit hanging on printing page with OpenLayers3 content when run with uWSGI and NGINX?

I'm using Django served by uWSGI and NGINX.
Ubuntu 14.04.1 LTS 64-bit
Python 3.4
Django 1.7.4
uWSGI 1.9.17.1-debian (64bit)
NGINX 1.4.6
python-pdfkit 0.5.0
wkhtmltopdf 0.12.2.1
OpenLayers v3.0.0
When I try running pdfkit.from_url(...) to print a map to pdf the request times out.
More specifically it hangs in python's subprocess.py communicate, self._communicate:
with _PopenSelector() as selector:
if self.stdin and input:
selector.register(self.stdin, selectors.EVENT_WRITE)
if self.stdout:
selector.register(self.stdout, selectors.EVENT_READ)
if self.stderr:
selector.register(self.stderr, selectors.EVENT_READ)
while selector.get_map():
...
selector.get_map() always returns a valid result, ensuring an infinite loop.
If I run this in the Django development server (instead of uWSGI+NGINX) everything runs fine.
in my view:
wkhtmltopdfBinLocationString = '/usr/local/bin/wkhtmltopdf'
wkhtmltopdfBinLocationBytes = wkhtmltopdfBinLocationString.encode('utf-8')
#this fixes some leftover python2 assumptions about strings
config = pdfkit.configuration(wkhtmltopdf=wkhtmltopdfBinLocationBytes)
pdfkit.from_url(reportPdfUrl, reportPdfFile, configuration=config, options={
'javascript-delay': 1500
})
Several places I have seen answers along the line of "set the close-on-exec flag on the socket" solving similar issues.
Is this something I can set from my "from_url" options (wkhtmltopdf does not accept it by that name) or can I configure uWSGI to assume 'close-on-exec'? I have not been able to make either of these work, but maybe I just need help with changing my uWSGI customization file:
[uwsgi]
workers = 1
chdir = [...]
plugins = python34
wsgi-file = [...]/wsgi.py
pythonpath = [...]
I tried something like
close-on-exec = true
but that didn't seem to do anything.
NOTE: the wsgi.py file is simple:
"""
WSGI config for dst project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
"""
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "[my_project].settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
Any thoughts?

Working with django : Proxy setup

I have a local development django setup with apache. The problem is that on the deployment server there is no proxy while at my workplace I work behind a http proxy, hence the request calls fail.
Is there any way of making all calls from requests library go via proxy. [ I know how to add proxy to individual calls using the proxies parameter but is there a global solution ? ]
I got the same error reported by AmrFouad. At last, it fixed by updating wsgi.py as follows:
os.environ['http_proxy'] = "http://proxy.xxx:8080"
os.environ['https_proxy'] = "http://proxy.xxx:8080"
Add following lines in your wsgi file.
import os
http_proxy = "10.10.1.10:3128"
https_proxy = "10.10.1.11:1080"
ftp_proxy = "10.10.1.10:3128"
proxyDict = {
"http" : http_proxy,
"https" : https_proxy,
"ftp" : ftp_proxy
}
os.environ["PROXIES"] = proxyDict
And Now you can use this environment variable anywhere you want,
r = requests.get(url, headers=headers, proxies=os.environ.get("PROXIES"))
P.S. - You should have a look at following links
Official Python Documentation for Environment Variables
Where and how do I set an environmental variable using mod-wsgi and django?
Python ENVIRONMENT variables
UPDATE 1
You can do something like following so that proxy settings are only being used on localhost.
import socket
if socket.gethostname() == "localhost":
# do something only on local server, e.g. setting os.environ["PROXIES"]
os.environ["PROXIES"] = proxyDict
else:
# Set os.environ["PROXIES"] to an empty dictionary on other hosts
os.environ["PROXIES"] = {}

django with twisted web - wgi and vhost

I have a project which has a directory setup like:
myproject
someapp
sites
foo
settings.py - site specific
settings.py - global
I am using twisted web.wsgi to serve this project. The problem am I running into is setting up the correct environment.
import sys
import os
from twisted.application import internet, service
from twisted.web import server, resource, wsgi, static, vhost
from twisted.python import threadpool
from twisted.internet import reactor
from django.core.handlers.wsgi import WSGIHandler
from django.core.management import setup_environ,ManagementUtility
sys.path.append(os.path.abspath("."))
sys.path.append(os.path.abspath("../"))
DIRNAME= os.path.dirname(__file__)
SITE_OVERLOADS = os.path.join(DIRNAME,'sites')
def import_module(name):
mod = __import__(name)
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod,comp)
return mod
def buildServer():
hosts = [d for d in os.listdir(SITE_OVERLOADS) if not os.path.isfile(d) and d != ".svn"]
root = vhost.NameVirtualHost()
pool = threadpool.ThreadPool()
pool.start()
reactor.addSystemEventTrigger('after', 'shutdown', pool.stop)
for host in hosts:
settings = os.path.join(SITE_OVERLOADS,"%s/settings.py" % host)
if os.path.exists(settings):
sm = "myproject.sites.%s.settings" % host
settings_module = import_module(sm)
domain = settings_module.DOMAIN
setup_environ(settings_module)
utility = ManagementUtility()
command = utility.fetch_command('runserver')
command.validate()
wsgi_resource = wsgi.WSGIResource(reactor,pool,WSGIHandler())
root.addHost(domain,wsgi_resource)
return root
root = buildServer()
site = server.Site(root)
application = service.Application('MyProject')
sc = service.IServiceCollection(application)
i = internet.TCPServer(8001, site)
i.setServiceParent(sc)
I am trying to setup vhosts for each site which has a settings module in the subdirectory "sites". However, it appears that the settings are being shared for each site.
Django projects within the same Python process will share the same settings. You will need to spawn them as separate processes in order for them to use separate settings modules.
Since your goal is a bunch of shared-nothing virtual hosts, you probably won't benefit from trying to set up your processes in anything but the simplest way. So, how about changing your .tac file to just launch a server for a single virtual host, starting up a lot of instances (manually, with a shell script, with another simple Python script, etc), and then putting a reverse proxy (nginx, Apache, even another Twisted Web process) in front of all of those processes?
You could do this all with Twisted, and it might even confer some advantages, but for just getting started you would probably rather focus on your site than on minor tweaks to your deployment process. If it becomes a problem that things aren't more integrated, then that would be the time to revisit the issue and try to improve on your solution.