Using wsgi.py correctly in Django - python

When I deploy my Django site I'm a little confused about the wsgi.py file and how locally it is used vs in production with Gunicorn.
Locally I have this file structure.
demo/
__init__.py
settings.py
urls.py
wsgi.py
manage.py
Settings.py has the following setting...WSGI_APPLICATION = 'demo.wsgi.application'
However once I deployed the app running on Gunicorn I get an error saying it could not find the wsgi.py file, in order to get it to work I have to create the file again like this...
demo/
__init__.py
settings.py
urls.py
wsgi.py
manage.py
wsgi.py
This now works but it suggests to me that Gunicorn ignores the WSGI_APPLICATION setting in Djangos setting file demo/settings.py, right? If so, where does Gunicorn get its own reference to the location for the wsgi.py file and what is different locally?
This is my Gunicorn setup incase that matters...
[program:gunicorn_process]
command=gunicorn wsgi:application -c /srv/test/gunicorn.conf.py
directory=/srv/test
user=root
autostart=true
autorestart=true
redirect_stderr=true
gunicorn.conf.py
bind = "127.0.0.1:8001"
workers = 3
worker_class = 'gevent'

You are correct that Gunicorn ignores the WSGI_APPLICATION setting. This setting is only used to specify the wsgi application that the runserver command uses.
Gunicorn does not know anything about Django, but you can specify in which module Gunicorn should look for the application. Right now it looks for an application attribute in the wsgi module:
command=gunicorn wsgi:application ...
To use the file in demo/, you must specify the full module path in the Gunicorn command:
command=gunicorn demo.wsgi:application ...

Related

How to always let heroku run a command on deployment for a django project?

I was working on a django project. The Procfile is the place that heroku always looks on before deployment.
Currently it is configured this way and it works all fine.
web: python manage.py collectstatic --no-input; gunicorn project_folder.wsgi --log-file - --log-level debug
This means it runs collectstatic command every time I make any changes in my project and deploy it on server. Can the same thing apply to run a background task? This background task needs to run automatically after my project is deployed.
python manage.py process_tasks is what I type in my command to trigger this background_task in django on my local server. So, would something like this help invoke it the same way as python manage.py collectstatic is (that is collecting all static files from my static folder)?
web: python manage.py collectstatic --no-input; python manage.py process_tasks; gunicorn project_folder.wsgi --log-file - --log-level debug
Did you try the release process type? (as mentioned here)
web: python manage.py collectstatic --no-input; gunicorn project_folder.wsgi --log-file - --log-level debug
release: python manage.py process_tasks
It should run the release command after deployment is complete.

Heroku local invalid port number or address:port pair - deploying django app

I have this ProcFile file following this guidelines for django app deployment on section Build your app and run it locally in order to test it locally you have to run this command.
web: python manage.py runserver 0.0.0.0:$PORT
Then running heroku local or heroku local web got me into this error:
CommandError: "0.0.0.0:$PORT" is not a valid port number or address:port pair.
You must not use runserver in production. Use gunicorn as the docs and comments suggest.
For local:
If you follow this official heroku tutorial and you are running it on Window platform locally, instead of $PORT, you have to use %PORT% at your Procfile.windows:
web: python manage.py runserver 0.0.0.0:%PORT%
since window does not interpret $PORT expression which only applicable in Unix shells.
If one using waitress as WSGI and wanna run it locally on Window platform, your Procfile should looks like this:
web: waitress-serve --port=%PORT% wsgi:your_app
For real online deployment:
simply include gunicorn package in requirementx.txt and your Procfile should be in this way:
web: gunicorn wsgi:your_app
If you are using waitress, you need to change back to $PORT, and set it in this way instead of fixed port number since Heroku assigns port to your app dynamically. Also, do make sure the host is set to 0.0.0.0 so your app is available externally.
For a django project in heroku you must have a Procfile like this:
web: gunicorn yourapp.wsgi
The filename must be Procfile, and not ProcFile
If you want to run into development you can either $ python manage.py runserver in your shell (heroku independent) or run $ heroku local with a valid production Procfile

Django app on AWS Elastic Beanstalk - DJANGO_SETTINGS_MODULE

Where should the DJANGO_SETTINGS_MODULE environment variable be set?
Multiple possible locations:
In a config file (.ebextensions) as follows:
option_settings: aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: "app.settings"
In the wsgi.py file before application is loaded
In manage.py (I also see this on different Django projects on the web)
If I don't specify it in wsgi.py, it looks like it can't be found at all. Therefore, I wonder if the environment variables set in .ebextensions are set before wsgi.py is loaded.
Any idea?
Introduce your wsgi.py in a config file in .ebextensions
django_aws_eb.config:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: "my_site/wsgi.py"
Specifly your DJANGO_SETTING_MODULE in your `wsgi.py' file
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_site.settings")
application = get_wsgi_application()
aws beanstalk first looks for configs in .ebextension to then locate wsgi.py to then locate settings.
more info: Configure Your Django Application for Elastic Beanstalk

Gunicorn failed to load Flask application

I have a Flask app I am trying to serve via Gunicorn.
I am using virtualenv and python3. If I activate my venv cd to my app base dir then run:
gunicorn mysite:app
I get:
Starting gunicorn
Listening at http://127.0.0.1:8000
DEBUG:mysite.settings:>>Config()
...
Failed to find application: 'mysite'
Worker exiting
Shutting down: master
Reason: App failed to load
Looking in /etc/nginx/sites-available I only have the file 'default'. In sites-enabled I have no file.
In my nginx.conf file I have:
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
App structure:
mysite #this is where I cd to and run gunicorn mysite:app
--manage.py
--/mysite
----settings.py
----__init__.py
in manage.py for mysite I have following:
logger.debug("manage.py entry point")
app = create_app(app_name)
manager = Manager(app)
if __name__ == "__main__":
manager.run()
In __init__.py file:
def create_app(object_name):
app = Flask(__name__)
#more setup here
return app
In my settings.py in the app directory
class Config(object):
logger.debug(">>Config()") #this logs OK so gunicorn is at least starting in correct directory
From inside the virtualenv if I run
print(sys.path)
I find a path to python and site-packages for this virtualenv.
From what I have read to start gunicorn it's just a matter of installing it and running gunicorn mysite:app
Running gunicorn from the parent directory of mysite I get the same failed to find application: 'mysite', App failed to load error, but don't get the DEBUG...Config() logged (as we are clearly in the wrong directory to start in). Running gunicorn from mysite/mysite (clearly wrong) I get and Exception in worker process ereor, ImportError: No module named 'mysite'.
Any clues as to how I can get gunicorn running?
You're pointing gunicorn at mysite:app, which is equivalent to from mysite import app. However, there is no app object in the top (__init__.py) level import of mysite. Tell gunicorn to call the factory.
gunicorn "mysite:create_app()"
You can pass arguments to the call as well.
gunicorn "mysite:create_app('production')"
Internally, this is equivalent to:
from mysite import create_app
app = create_app('production')
Alternatively, you can use a separate file that does the setup. In your case, you already initialized an app in manage.py.
gunicorn manage:app

Django. Using multiple settings files with Heroku

I am trying to follow the advice of the book "Two Scoops of Django" and although it is a really good book, I think it this section is unclear.
So, I split my settings file and created a folder like this:
settings/
__init__.py
base.py (allmost everything there)
local.py (dev. specific settings)
production.py (settings for Heroku)
most of the settings are in the base.py file
in local.py I have this:
# settings/local.py
from .base import *
DEBUG = True
TEMPLATE_DEBUG = DEBUG
INSTALLED_APPS += ("debug_toolbar", "django_extensions", "south",)
in production.py I have this:
from .base import *
INSTALLED_APPS += ("gunicorn",)
When I run locally:
python manage.py runserver 7000 --settings=appname.settings.local
python manage.py runserver 7000 --settings=appname.settings.production
everything works fine.
But when I push changes to Heroku, I get the log:
File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/util.py", line 354, in import_app
raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
So, I guess Heroku is not finding my settings files, I don't know how to fix this (it might be very simple).
Two Scoops of Django is kind of ironic here, it writes "Platform as Service - See section 25.2" and then in that section it just writes "read Platform Documentation" : /
After you have logged into heroku with heroku login you can check your configs by running:
heroku config.
If you dont see a SECRET_KEY and DJANGO_SETTINGS_MODULE you can set them by running:
heroku config:set SECRET_KEY='secret_key_goes_here'
and
heroku config:set DJANGO_SETTINGS_MODULE=mysite.settings.production
Finally, make sure that you have the following syntax inside of your production setting file:
SECRET_KEY = os.environ['SECRET_KEY']
The above intstructions are for the following project structure
-myproject
-app1
-app2
-mysite
-settings
__init__.py
base.py
dev.py
production.py
-manage.py
-Pipfile
-Procfile
-requirements.txt
You can use the environment variable DJANGO_SETTINGS_MODULE to specify a default settings module:
https://docs.djangoproject.com/en/dev/topics/settings/#envvar-DJANGO_SETTINGS_MODULE
On local Linux machine:
export DJANGO_SETTINGS_MODULE=settings.local
On Heroku:
heroku config:set DJANGO_SETTINGS_MODULE=settings.production

Categories

Resources