Coding With Fun
Home Docker Django Node.js Articles FAQ

Use WSGI for deployment


May 14, 2021 Django


Table of contents


Brief introduction

Django's primary deployment platform is WSGI, which is the Python standard for Web servers and applications.

Django's startproject management command sets you a minimal default WSGI configuration that you can adapt to your project's needs and guide any WSGI-compliant application server.

Django includes the following getting started documentation for WSGI servers:

The application object

A key concept for deploying with WSGI is Callable, which the app application server uses to communicate with your code. Usually the application is provided as an object named in the Python module that is accessible to the server.

The startproject command creates a /wsgi.py file that contains such an application callable file.

Django's development servers and production WSGI deployments both use it.

The WSGI server application gets the path of the callable object from its configuration. D jango's built-in server, the runserver command, reads WSGI_APPLICATION settings of the computer. By default, it is set to .wsgi.application, which points to the application in which the object/wsgi.py.

Configure the settings module

When the WSGI server loads your application, Django needs to import the settlings module - defining the place for the entire application.

Django uses DJANGO_SETTINGS_MODULE environment variables to find the appropriate setup module. I t must contain a dashed path to the settings module. Y ou can use different values for development and production. It all depends on how you organize your settings.

If this variable is not set, the default wsgi.py set it to mysite.settings, where mysite is the name of the project. This is how runserver discovers default settings files by default.

Note: Because environment variables are process-wide, this is not valid when you run multiple Django sites in the same process. This happens mod_wsgi the united states.

To avoid this problem, use a mod_wsgi daemon pattern for each site in its own daemon, or enforce in to override values in the environment. os.environ["DJANGO_SETTINGS_MODULE"] = "mysite.settings"``wsgi.py

Apply WSGI middleware

To apply WSGI middleware, you can wrap the application object. For example, you can add these rows wsgi.py:

from helloworld.wsgi import HelloWorldApplication
application = HelloWorldApplication(application)

If you want to use the Django application with another framework WSGI application, you can also replace the Django WSGI application with a custom WSGI application, which later delegates it to the Django WSGI application.

Django and Gunicorn use

Gunicorn ("Green Unicorn") is a pure Python WSGI server for UNIX. It has no dependencies and can use the installation pip.

Install Gunicorn

By running the installation gunicorn. For more details, see the gunicorn documentation.

python -m pip install gunicorn

Run Django as a generic WSGI application in Gunicorn

After the Gunicorn is installed, the gunicorn is provided with a command to start the Gunicorn server process. The simplest call to gunicorn is to pass the location of the module containing an object called a WSGI application, which should look like this for a typical Django project:

gunicorn myproject.wsgi

This starts a process that runs a thread that is listening to 127.0.0.1:8000. It requires your project to be on the manage.py Python path;

For additional tips, see The deployment documentation for Gunicorn.

How to use Django with uWSGI

uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server that uses pure C coding.

You can also take a look

The uWSGI documentation provides a tutorial covering Django, nginx, and uWSGI (many possible deployment settings). The following documents focus on how to integrate Django with uWSGI.

Prerequisite: uWSGI

The uWSGI wiki describes several installation procedures. W ith Python Package Manager Pip, you can install any uWSGI version with a single command. For example:

# Install current stable version.
$ python -m pip install uwsgi

# Or install LTS (long term support).
$ python -m pip install https://projects.unbit.it/downloads/uwsgi-lts.tar.gz

uWSGI model

uWSGI runs on the client-server model. Your Web server (e.g. nginx, Apache) communicates with the django-uwsgi "worker" process to provide dynamic content.

Configure and start the uWSGI server for Django

uWSGI supports a variety of configuration processes.

This is the sample command to start the uWSGI server:

uwsgi --chdir=/path/to/your/project \
  --module=mysite.wsgi:application \
  --env DJANGO_SETTINGS_MODULE=mysite.settings \
  --master --pidfile=/tmp/project-master.pid \
  --socket=127.0.0.1:49152 \     # can also be a file
  --processes=5 \                 # number of worker processes
  --uid=1000 --gid=2000 \         # if root, uwsgi can drop privileges
  --harakiri=20 \                 # respawn processes taking more than 20 seconds
  --max-requests=5000 \           # respawn processes after serving 5000 requests
  --vacuum \                     # clear environment on exit
  --home=/path/to/virtual/env \   # optional path to a virtual environment
  --daemonize=/var/log/uwsgi/yourproject.log     # background the process

Suppose you have a top-level project package called mysite, and mysite/wsgi .py contains a module containing the WSGI application object. I f you run with the latest version of Django (instead of using your own project name), this will be your layout. I f the file does not exist, you need to create it. S ee the "How to deploy using WSGI" documentation for the default content that should be placed in this file and other content that you can add. django-admin startproject mysite``mysite

Django-specific options are as follows:

  • chdir: The directory path that needs to be on Python's import path - that is, the directory that contains the mysite package.
  • module: The WSGI module to use - maybe mysite.wsgi is a module created by startproject.
  • env: Should contain at least DJANGO_SETTINGS_MODULE.
  • Home: An optional path to the project virtual environment.

Example ini profile:

[uwsgi]
chdir=/path/to/your/project
module=mysite.wsgi:application
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000
daemonize=/var/log/uwsgi/yourproject.log

Examples of ini profile usage:

uwsgi --ini uwsgi.ini

Fix Unicode EncodeError file upload

If UnicodeEncodeError sees files with a file name that contains non-ASCII characters, be sure to configure uWSGI to accept non-ASCII file names by adding them to your uwsgi .ini:

env = LANG=en_US.UTF-8

For more information, see the "Files" section of the Unicode Reference Guide.

Refer to the uWSGI documentation for managing uWSGI processes for information on starting, stopping, and reloading uWSGI work programs.

Use Django and Django in Apache and mod_wsgi

Deploying Django mod_wsgi with Apache and technology is a proven way to get Django into production.

mod_wsgi is an Apache module that can host any Python WSGI application, including Django. Django can be used with mod_wsgi version of Apache that supports the application.

The official documentation is mod_wsgi source of all the details about how mod_wsgi is used. You may need to start with the installation and configuration documentation.

Basic configuration

After installing and mod_wsgi, edit the apache server's httpd.conf file and add the following.

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonHome /path/to/venv
WSGIPythonPath /path/to/mysite.com

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

The first bit of the WSGIScriptAlias line is the basic URL path (/for root URL) on which you want to serve the application, and the second is the location of the "WSGI file" - see below - on the system, usually in the project internal package (mysite in this example). This tells Apache to use the WSGI application defined in the file to service any request under a given URL.

If you install the project's Python dependency in , use the add path. F or more details, see mod_wsgi virtual environment guide. virtual environmentWSGIPythonHome

The WSGIPythonPath line ensures that your project package can be used to import on the Python path; import mysite

This 'section ensures that Apache has access to your wsgi.py' file.

Next, we need to make sure that the wsgi.pyWSGI application object exists. S tarting with Django 1.4, startproject will create one for you. O therwise, you will need to create it. See the WSGI overview documentation for the default content that should be placed in this file and other content that can be added.

Warning: If you run mod_wsgi Django sites in a single process, all sites will use the settings of the site that happens to run first. This can be resolved by:

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")

In the wsgi.py, to:

os.environ["DJANGO_SETTINGS_MODULE"] = "{{ project_name }}.settings"

Or by using mod_wsgi daemon mode and make sure that each site is running in its own daemon.

Fix Unicode EncodeError file upload

If UnicodeEncodeError sees files with non-ASCII characters when uploading a file name, make sure apache is configured to accept non-ASCII file names:

export LANG='en_US.UTF-8'
export LC_ALL='en_US.UTF-8'

A common place to place this configuration is /etc/apache2/envvars.

For more information, see the "Files" section of the Unicode Reference Guide.

Use mod_wsgi daemon mode

It is recommended that you run the mod_wsgi (on non-Windows platforms). T o create the required daemon group and delegate Django instances to run in it, you will need to add the appropriate WSGIDaemon Process and WSGIProcessGroup instructions. If you use daemon mode, a further change to the above configuration is that you cannot use WSGIPythonPath;

WSGIDaemonProcess example.com python-home=/path/to/venv python-path=/path/to/mysite.com
WSGIProcessGroup example.com

If you want to service items in a subdirect https://example.com/mysite (in this example), you can add WSGIScriptAlias to the above configuration:

WSGIScriptAlias /mysite /path/to/mysite.com/mysite/wsgi.py process-group=example.com

For more information about setting daemon mode, see mod_wsgi official documentation.

The service file

Django itself does not provide files;

We recommend using a separate Web server (that is, a server that is not running Django at the same time) to provide media services. Here are some good options:

  • Nginx's
  • Lite version of Apache

However, if you have no choice but to provide media files on the same Apache as Virtual HostDjango, you can set Up Apache to use some URLs as static media and others to provide using Django's mod_wsgi interface.

This example sets Django in the site root, but tees robos.txt, favicon.ico and in what/static/and/media/URL space as static files. All other URLs will be mod_wsgi provide:

Alias /robots.txt /path/to/mysite.com/static/robots.txt
Alias /favicon.ico /path/to/mysite.com/static/favicon.ico

Alias /media/ /path/to/mysite.com/media/
Alias /static/ /path/to/mysite.com/static/

<Directory /path/to/mysite.com/static>
Require all granted
</Directory>

<Directory /path/to/mysite.com/media>
Require all granted
</Directory>

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

Provide management files

In django.contrib.staticfiles INSTALLED_APPS the Django development server automatically provides static files for admin applications (and all other installed applications). H owever, this is not the case when you use any other server placement. You are responsible for setting up Apache or any Web server you use to provide administrative files.

The management file is located in the django/contrib/admin/static/adminDjango distribution().

We strongly recommend that you use django.contrib.staticfiles to work with administrative files (such as the static files collected by the management commands of the Web server listed in the last section, using this tool to colectstatic management commands STATIC_ROOT, and then configure your Web server service STATIC_ROOT STATIC_URL), but here are three other ways:

  1. Create a symbolic link from the document root to manage static files (which may be required in your Apache configuration by followingSymLinks).
  2. Alias, as shown above, uses instructions to alias the appropriate URL (possibly STATIC_URL plus admin/) as the actual location of the management file.
  3. Replication manages static files so that they are located in the root of the Apache document.

Authentication of the Django user database from Apache

Django provides a handler that allows Apache to authenticate users directly against Django's authentication backend.

Because keeping in sync with multiple Apache authentication databases is a common problem, Apache can be configured to authenticate directly against Django's authentication system. T his requires the Apache version, which is 2.2 mod_wsgi, and 2.0. For example:

  • Only static/media files are provided directly from Apache to authenticated users.
  • Have certain permissions to verify access to the Subversion repository for Django users.
  • Allows some users to connect to webDAV mod_dav created using a user."

Note: If you already have a custom user model installed and want to use this default authentication handler, it must support a is_active property. I f you want to use group-based authorization, the custom user must have a relationship called Group that refers to a related object with a Name field. If your customization does not meet these requirements, you can also specify your own mod_wsgi authentication handler.

Use authentication to mod_wsgi

Note: When used in the following configuration, assume that your Apache instance runs only one Django application. I f you are running multiple Django applications, see the mod_wsgi Define Application Groups section of the documentation for more information about this setting. WSGIApplicationGroup %{GLOBAL}

Make sure that you have installed and activated mod_wsgi, and that you have followed the steps mod_wsgi set up Apache.

Next, edit your Apache configuration to add locations that only authenticated users can view:

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonPath /path/to/mysite.com

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup %{GLOBAL}

<Location "/secret">
  AuthType Basic
  AuthName "Top Secret"
  Require valid-user
  AuthBasicProvider wsgi
  WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
</Location>

The WSGIAuthUserScript instruction tells mod_wsgi check_password to perform the function in the specified wsgi script and pass the username and password received from the prompt. I n this example, it is the same as defining the application WSGIAuthUserScript created by django-admin startproject. WSGIScriptAlias

Use Apache 2.2 and authentication together

Make sure mod_auth_basic and mod_authz_user are loaded.

These may be statically compiled into Apache, or you may need to use LoadModule to dynamically load them in your httpd.conf:

LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authz_user_module modules/mod_authz_user.so

Finally, mysite.wsgi edits check_password script by importing the following features to link Apache authentication to the site's authentication mechanism:

import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

from django.contrib.auth.handlers.modwsgi import check_password

from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()

Requests starting at /secret/now will require the user to authenticate.

mod_wsgi additional details and information about alternative authentication methods are provided in the access control mechanism documentation.

mod_wsgi and Django group authorization

mod_wsgi also provides the ability to limit specific locations to group members.

In this case, the Apache configuration should look like this:

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup %{GLOBAL}

<Location "/secret">
  AuthType Basic
  AuthName "Top Secret"
  AuthBasicProvider wsgi
  WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
  WSGIAuthGroupScript /path/to/mysite.com/mysite/wsgi.py
  Require group secret-agents
  Require valid-user
</Location>

To support the WSGIAuthGroupScript instruction, the same WSGI script mysite.wsgi must also import the groups_for_user function, which returns the list group to which a given user belongs.

from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user

If there is a need/secret/, the user is now required to be a member of the Secret Agents group.

For more information: https://docs.djangoproject.com/en/3.0/