Daniel Diaz
Posted on February 18, 2021
Deploying a Django App
Deploying a Django application to the internet could be difficult, but there are free and dedicated hosting platforms designed for deploy specific frameworks to the Internet.
Heroku may be the perfect choose for those how want a starting free web hosting and sub-domain, and an easy configurable hosting.
Pre-requirements:
- You need to have Heroku CLI installed, and be logged in to your account. If you don't have it installed, check out the official docs, Here
Now that you have it installed and you are logged in, you can continue with the Python stuff π.
Necessary packages to deploy on Heroku:
Now make sure to create a virtual environment, my preferred way is virtualenv
:
First install it with pip install virtualenv
, create a virtual env and create it:
virtualenv venv
#then
source venv/bin/activate
# Depending on your shell, you could run a different command.
Install Django and your Python development tools:
pip install django
You need some packages to deploy an application to heroku, so let's get into it:
If you just want a command to install most packages you need, copy the line below:
pip install gunicorn django-heroku python-decouple
Let's start with the package that handles most of the server operations: Gunicorn is an easy yet powerful Python HTTP server.
pip install gunicorn
Django Heroku, allow us to don't worry of our settings in the Heroku server.
pip install django-heroku
This package comes with other important packages that facilitates us the deployment in the fields, of static files whitenoise
, a postgreSQL adapter psycopg
, a package that helps to connect with the Database dj-database-url
, and django-heroku itself.
This is almost everything but only a package is left π :
pip install python-decouple
This package helps us to pass python environmental variables on Django, we will se it later I promiseπ.
Now let's run pip freeze
, you should get something like this:
asgiref==3.3.1
dj-database-url==0.5.0
Django==3.1.6
django-heroku==0.3.1
gunicorn==20.0.4
psycopg2==2.8.6
python-decouple==3.4
pytz==2021.1
sqlparse==0.4.1
whitenoise==5.2.0
Run this command to create a requirements.txt
file that Heroku will use to install of the packages needed.
pip freeze > requirements.txt
Create a Procfile
# Run this in the root directory of the app
touch Procfile
Open the file and copy the following file:
web: gunicorn (Your app).wsgi
This tells Heroku, that it must run a web process, with gunicorn as HTTP server and with a wsgi
file located in (Your app)
. Remember to change (Your app)
with the name of your project.
Settings.py file
We just installed a lot of stuff, but now it's time to apply all of this in the settings.py
file, but first Pro tip.
Pro Tip:
Before continuing modifying the settings file, do the following things:
Duplicate the settings.py
file of your project, and rename it as settings_local.py
,you will leave that file untouched, and use that configuration, while developing the application in local.
To run the server with the local settings just run the following command:
python manage.py runserver --settings=(Your app).settings_local
Now after that, continue configuring the production environment.
Modifying the settings:
Importing modules
At the top of the file import the following modules:
# Import to serve staticfiles correctly
import os
import django_heroku
import dj_database_url
from decouple import config
Static files
In the MIDDLEWARE
variable, set whitenoise middleware below the Security Middleware:
MIDDLEWARE = [
# 'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# ...
]
Now go to the bottom of the app, where you could find the following commentaries:
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
Below paste this codeπ₯οΈ:
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
Perfect, now our static files should be managed by Whitenoise.
Last step
At the very bottom of the file set the django heroku settings
django_heroku.settings(locals())
That's all of you need to deploy an app to Heroku, good luck!
Create a Pipeline, from a Github Repository
Login or Create an account on Heroku, go to dashboard and click in the New Button.
Now click on create a new pipeline:
After that you will be redirected, to the pipeline, click on the add app button in order to create a new app.
Click and add your new app.
From now you will get a fully featured dashboard with the app.
Go to Deploy tab, and in the bottom you will get a button where you can deploy your app. Now click on that button and deploy the main branch.
Extra:
Troubleshooting:
Probably you will get a lot of errors before you can publish your app to the internet, so I'm going to tell you the most common problems and how to fix them.
Static files errors:
One of the most common errors that you will get, may be related with static files.
Error:
-----> $ python manage.py collectstatic --noinput
Post-processing 'css/owl.carousel.min.css' failed!
Traceback (most recent call last):
File "manage.py", line 22, in <module>
main()
File "manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
utility.execute()
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/base.py", line 330, in run_from_argv
self.execute(*args, **cmd_options)
File "/app/.heroku/python/lib/python3.6/site-packages/django/core/management/base.py", line 371, in execute
output = self.handle(*args, **options)
File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 194, in handle
collected = self.collect()
File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 138, in collect
raise processed
whitenoise.storage.MissingFileError: The file 'css/owl.video.play.png' could not be found with <whitenoise.storage.CompressedManifestStaticFilesStorage object at 0x7fab586a2710>.
The CSS file 'css/owl.carousel.min.css' references a file which could not be found:
css/owl.video.play.png
Please check the URL references in this CSS file, particularly any
relative paths which might be pointing to the wrong location.
! Error while running '$ python manage.py collectstatic --noinput'.
See traceback above for details.
You may need to update application code to resolve this error.
Or, you can disable collectstatic for this application:
$ heroku config:set DISABLE_COLLECTSTATIC=1
https://devcenter.heroku.com/articles/django-assets
! Push rejected, failed to compile Python app.
! Push failed
As you can see, the error is caused because of a css file pointing to another file that doesn't exist.
Heroku and Django are very sensitive with static files so if a pointing file doesn't exist, an error will occur.
To fix this particular error, set the environment key, DISABLE_COLLECTSTATIC
and run locally the collectstatic
command.
# Root directory
heroku config:set DISABLE_COLLECTSTATIC=1
# collect static
python manage.py collectstatic
Push the code and deploy the app, this problem should be solved.
Fixing other errors:
To fix an error in production, We will use a logger in Django.
Paste the code below, this will give you a Django logger in production, which you can access with the following command.
# Django logger
# Debugging in heroku live
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': ('%(asctime)s [%(process)d] [%(levelname)s] ' +
'pathname=%(pathname)s lineno=%(lineno)s ' +
'funcname=%(funcName)s %(message)s'),
'datefmt': '%Y-%m-%d %H:%M:%S'
},
'simple': {
'format': '%(levelname)s %(message)s'
}
},
'handlers': {
'null': {
'level': 'DEBUG',
'class': 'logging.NullHandler',
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose'
}
},
'loggers': {
'testlogger': {
'handlers': ['console'],
'level': 'INFO',
}
}
}
DEBUG_PROPAGATE_EXCEPTIONS = True
COMPRESS_ENABLED = os.environ.get('COMPRESS_ENABLED', False)
# Heroku logs
heroku logs --tail
Now you will get a real time logger to debug your application on production.
Thanks for your time hopefully this tutorial will be useful for you π€.
Follow me in My blog,
to get more awesome tutorials like this one.
Please consider supporting me on Ko-fi you help me a lot to
continue building this tutorials!.
Posted on February 18, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.