Running a Django Application on Windows Server 2012 with IIS

This is a first for me since under normal circumstances we run all our Django applications on Linux with Nginx, but we’re in the process of developing an application for another department and due to the requirements around this project, we’ll be handing the code off to them to deploy. They don’t have any experience with Linux or web servers other than IIS, so I recently took up the challenge of figuring out how to run Django applications on Windows Server 2012 with IIS.

Based on the dated or complete lack of information around this I’m assuming it’s not something that’s very common in the wild, so I thought I’d share what I came up with in case others need to do this.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Assumptions and Caveats

  1. The operating system is Windows Server 2012 R2, 64-bit. If another variant of the operating system is being used, these instructions may not work properly.
  2. All of the software versions referenced in this document are current as of the date of this blog post.
  3. All actions are performed as the Administrator user, or another user with Administrator rights.
  4. Depending on the audience, some of these steps may seem unnecessarily pedantic. They were originally written to be as foolproof as possible and to make these steps as thorough and complete as they can be. I decided not to simplify or abbreviate anything for this blog post.
  5. The version of Django that is current as of the time of this writing is 1.9.8. If any of the Django-related configuration settings change in the future, the settings outlined in this document may no longer be valid. For example, the details of the call to the Django WSGI handler are specific to this version of Django. They have been different in prior versions of Django, and may need to be updated in the future to reflect changes in Django.
  6. We’ll be creating a sample application called foo directly on the server. In real-world circumstances you’ll be deploying a completed application to the server, but I thought this was a good way to illustrate the steps and how all the pieces fit together.
  7. If you install things in different locations than outlined here, or put your application in a different location than outlined here, obviously you’ll have to adjust paths in configuration settings accordingly.

Prerequisites for Running Django Applications on IIS

If you want to target Windows Server and IIS as the production environment for your Django application, there aren’t really any issues of concern other than including the wfastcgi Python package (https://pypi.python.org/pypi/wfastcgi) in your application.
wfastcgi is maintained by Microsoft as part of Python Tools for Visual Studio (https://www.visualstudio.com/en-us/features/python-vs.aspx), and provides a file that serves as the entry point of the IIS handler for WSGI applications in Python. It’s similar in purpose to a tool like Gunicorn (http://gunicorn.org), with the end result being that requests that come into IIS are handed off to the Python application for processing.
wfastcgi can be installed with pip:
pip install wfastcgi
You’ll also want to add wfastcgi to your Django application’s requirements.txt file to make sure it gets installed as part of the deployment of your application.
After installing wfastcgi the file wfastcgi.py will be in your Python environment’s site-packages directory. We’ll point to this file later when we’re configuring the IIS handler for Django.

Install Python

  1. Download the latest Windows x86-64 executable installer from https://python.org
  2. Double-click the Python installer. If you get a security warning at this point, click “Run” to continue.
  3. In the Python Setup dialog that appears, click “Customize Installation”
  4. On the Optional Features step, leave the default settings and click “Next”
  5. On the Advanced Options step, make the following changes:
    1. Check the “Install for all users” box (note that this will also check the “Precompile standard library” box)
    2. Check “Add Python to environment variables”
    3. In the input box below “Customize install location” change the value to the following:
      C:Python35
  6. Click “Install”
  7. When the installation is complete, click “Close”

Confirm the Python Installation

  1. Open a new Command Prompt. Note that if you already had a command prompt open you will need to close and reopen it, as the Python installation process added new environment variables and any open command prompts will not have the new environment variables available.
  2. Type python and press Enter. This should open a Python interpreter:
    1. If instead of seeing the Python interpreter you see the error “‘python’ is not recognized as an internal or external command …” this likely means the “Add Python to environment variables” box was not checked on the Advanced Options step of the installation process. If this occurs you can uninstall and reinstall Python and make sure to check the “Add Python to environment variables” checkbox, or add the following to the System environment “Path” variable:
      C:Python35;C:Python35Scripts
  3. Exit the Python interpreter by typing exit() and pressing Enter.
  4. Close the Command Prompt

Install IIS

Even if you already have IIS installed, you may need to go through these steps to install the CGI feature if it wasn’t installed as part of the original IIS installation.

  1. Open the Control Panel
  2. In the search box in the top right, type “windows features” (without the quotes)
  3. In the search results under “Programs and Features” click “Turn Windows features on or off.” This launches the Add Roles and Features Wizard.
  4. On the “Before you begin” step, click “Next”
  5. On the “Select installation type” leave the “Role-based or feature-based installation” radio button selected and click “Next”
  6. On the “Select destination server” step, leave the current server highlighted and click “Next”
  7. On the “Select server roles” step, scroll to the bottom of the list and check “Web Server (IIS)”
  8. In the “Add features that are required for Web Server (IIS)?” dialog that appears, leave the “Include management tools (if applicable)” checkbox checked and click “Add Features”
  9. On the “Select server roles” step, now that “Web Server (IIS)” is checked, click “Next”
  10. On the “Select features” step, leave the defaults and click “Next”
  11. On the “Web Server Role (IIS)” step, click “Next”
  12. On the “Select role services” step, scroll down to “Application Development,” expand that section, and check the “CGI” box. This will also check the “Application Development” checkbox. With “CGI” checked, click “Next.”
  13. On the “Confirmation” step, click “Install”
  14. Once the installation completes, click “Close”
  15. Close Server Manager
  16. Close Control Panel

Verify the IIS Installation

  1. Open a web browser on the server
  2. Enter http://localhost in the address bar and press Enter. You should see the default IIS page.
  3. If you don’t see the default IIS page:
    1. Open Control Panel
    2. Type “services” in the search box
    3. Under “Administrative Tools” click “View local services”
    4. Scroll to the bottom of the list and ensure you see “World Wide Web Publishing Service” listed, and that the status is “Running”

Create and Configure a Python Virtual Environment for Your Application

Python virtual environments are used to isolate application-specific Python environments from the system-wide Python environment. Even if you will only be running one application on a server, it’s good practice to create a virtual environment for your application to keep the virtual environment free from any unanticipated side effects of system updates.
  1. Open a Command Prompt
  2. Navigate to the root of the C: drive:
    cd C: [then press Enter]
  3. Create a new directory in which to store your virtual environments:
    mkdir virtualenvs [then press Enter]
  4. Navigate to the newly created virtualenvs directory:
    cd virtualenvs [then press Enter]
  5. Create a new virtual environment. We’ll use the name foo for the purposes of illustration. Note that if you change this, you’ll have to adjust the rest of the steps in this post accordingly.
    python -m venv foo [then press Enter]

Activate the Virtual Environment and Upgrade pip

With the virtual environment created, the next steps are to activate the virtual environment and update pip, Python’s package installer.
First, we’ll activate the virtual environment:
  1. Open a Command Prompt
  2. Navigate to the virtual environment’s directory:
    cd C:virtualenvsfoo [then press Enter]
  3. Activate the virtual environment:
    Scriptsactivate.bat [then press Enter]
  4. At this point you will see (foo) at the beginning of the command prompt, indicating the virtual environment is active:
    1. Once a virtual environment is active, all Python-related commands such as python, pip, etc. will be executed against the active virtual environment. For example, with the virtual environment active if a package is installed with pip, that package will only be available in the virtual environment, not in the system’s global Python environment.
Next, to ensure we don’t run into installation or security issues with pip, let’s upgrade it:
  1. In the same Command Prompt you opened above, with the virtual environment activated, run the following command:
    python -m pip install –upgrade pip [then press Enter]
    1. If an update for pip is available, it will be downloaded and installed

Install Django and Create a Sample Django Application

Typically, you’ll be installing requirements from a requirements.txt file that is part of the codebase for your application, but for the purposes of this installation guide we’ll install Django in our virtual environment, both to illustrate the steps involved as well as to ensure the virtual environment is working properly. Then we’ll create a sample Django application that we’ll use later to configure with IIS.
  1. In the same Command Prompt you opened above, with the virtual environment activated, install Django:
    pip install django [then press Enter]
  2. As outlined in the prerequisites section at the beginning of this document, you’ll also need to install wfastcgi in order for IIS to be able to pass requests off to Django:
    pip install wfastcgi [then press Enter]
  3. Navigate to the root of the C: drive:
    cd C: [then press Enter]
  4. Create a new directory in which we’ll put our application:
    mkdir apps [then press Enter]
  5. Navigate to the newly created apps directory:
    cd apps [then press Enter]
  6. Create a new Django project called foo:
    django-admin.py startproject foo [then press Enter]
  7. Navigate to the newly created foo project directory:
    cd foo [then press Enter]
  8. Start the Django development server:
    python manage.py runserver [then press Enter]
    1. You should see the following output:
  9. In a browser on the server, go to http://localhost:8000
    You should see the following:
  10. Go back to the Command Prompt and press Ctrl-C to stop the Django development server.

Configure IIS to Serve Django Applications

Thus far we’ve accomplished the following:
  1. Installed Python
  2. Installed IIS with CGI
  3. Created and activated a Python virtual environment
  4. Installed Django and wfastcgi in a Python virtual environment
  5. Created a new Django project
  6. Ran the Django project using the Django development server
With all the underlying infrastructure in place, the last step is to configure IIS to serve Django applications. The Django development server is not designed for production use, so using a production-quality web server such as IIS is mandatory for production applications.
As with previous steps you’ll need to adjust accordingly for the actual application you want to deploy, but for the purposes of this documentation we’ll configure IIS to serve the test Django application we created in the previous steps.

Configure FastCGI in IIS

  1. Open the IIS Manager by clicking the Windows button, clicking on Administrative Tools, and double-clicking Internet Information Services (IIS) Manager
  2. Click on the name of the server in the list on the left. If you see the following dialog box, check the box “Do not show this message” and click “No.” (You can always get to this later if necessary by clicking “Get New Web Platform Components” under “Actions” on the right-hand side of IIS Manager.)
  3. Double-click the “FastCGI Settings” icon
  4. Under “Actions” on the right-hand side click “Add application …”
  5. In the Add FastCGI Application dialog, in the “Full Path” box, type the path to the Python executable for the application’s virtual environment:
    C:virtualenvsfooScriptspython.exe
  6. In the Arguments input box, type the path to the wfastcgi.py file in the application’s virtual environment:
    C:virtualenvsfooLibsite-packageswfastcgi.py
  7. At this point your settings in the Add FastCGI Application dialog should look like this:
  8. With the Add FastCGI Application dialog box still open, under the “General” section, click on the “Environment Variables” line, then click the gray “…” button that appears next to (Collection) on the right-hand side of the line. This opens the EnvironmentVariables Collection Editor dialog.
  9. In the EnvironmentVariables Collection Editor dialog, click “Add”
  10. In the “Name properties” section on the right, click the input box to the right of “Name,” remove the “Name” text that is already in the input box, and enter DJANGO_SETTINGS_MODULE (note that this MUST be entered in ALL CAPS)
  11. Click the input box to the right of “Value” and enter foo.settings
  12. Click “Add” again and enter the following:
    Name: PYTHONPATH
    Value: C:appsfoo
  13. Click “Add” again and enter the following:
    Name: WSGI_HANDLER
    Value: django.core.wsgi.get_wsgi_application()
  14. At this point you will have three environment variables:
    1. NOTE: All of these settings are CASE-SENSITIVE. They must be entered with exactly the case indicated here in order to work.
  15. Click “OK” to close the EnviromentVariables Collection Editor
  16. Click “OK” to close the Add FastCGI Application dialog

Create and Configure a New IIS Web Site

Next we need to create a new web site in IIS for the Django application, and add a Handler Mapping to the newly created web site so that requests coming to the IIS web site are passed off to the Django application for processing.
  1. Open IIS Manager
  2. On the left-hand side under Connections, expand the tree under the server name by clicking on the arrow to the left of the server name
  3. Right-click on the Sites folder and click “Add Website …”
  4. For the site name enter foo
  5. For the physical path, type the following:
    C:appsfoo
  6. For the purposes of this example configuration, change the Port to 81, since the Default site is running on port 80. For a real-world application you’ll likely want to use name-based virtual hosting by adding bindings and run the site on port 80.
  7. You may leave the “Host name” blank. At this point the Add Website dialog should look like this:
  8. Click “OK”
Next, we’ll add a FastCGI handler mapping to this site so the requests coming into the site will be processed by the Django application.
  1. In IIS Manager, expand the Sites folder on the left-hand side and click on the foo site
  2. On the right, double-click “Handler Mappings”
  3. On the right, under “Actions,” click “Add Module Mapping”
  4. In the “Request path” box enter an asterisk: *
  5. Click the arrow on the right-hand side of the “Module” box and select “FastCgi Module”
    1. NOTE: Make sure to select FastCgi Module, NOT CgiModule
  6. In the “Executable” box, enter the following:
    C:virtualenvsfooScriptspython.exe|C:virtualenvsfooLibsite-packageswfastcgi.py
    1. Note that the character after python.exe is a pipe (|), which is entered by pressing Shift- on your keyboard
  7. In the “Name” box, enter Django Handler (you can call this whatever you want; it’s merely a friendly name for the module mapping)
  8. The Add Module Mapping dialog should now look like this:
  9. Click the “Request Restrictions” button and uncheck the “Invoke handler only if request is mapped to:” checkbox
  10. Click “OK” to close the Request Restrictions dialog
  11. Click “OK” to close the Add Module Mapping dialog
  12. When prompted “Do you want to create a FastCGI application for this executable?” click “No” since we created the application earlier.
    1. Note that you CAN have it create the FastCGI application for you from the module mapping, but the settings seem to be different and the end result isn’t fully editable. I also detailed how to create the FastCGI application to be as thorough as possible with all the various pieces involved.
  13. You will now see the Django Handler listed in the Handler Mappings for the foo website:
At this point everything should be working, so verify by loading the application in a browser.
  1. Open a browser on the server
  2. Browse to http://localhost:81
  3. You should see the following:
This is the same result as when we ran the Django test server earlier, but now the requests are being handled by IIS.

Configure Django and IIS to Serve Static Files

Now we have things more or less working but we aren’t quite done. If you browse to the Django admin page (http://localhost:81/admin), you’ll see something like this:
The reason things look a little strange is because IIS doesn’t know where things like the CSS and image files for the Django application are located. In the Django world these assets are referred to as “static files,” and we need to perform a couple of additional steps for IIS to be able to serve these files. This isn’t an issue during development since Django has a static file server built into it, but in production we’ll want IIS to handle serving these files.
How Django handles static files is a bit of a topic in and of itself, so for further information please consult the Django documentation (https://docs.djangoproject.com/en/1.9/howto/static-files/). In this guide we’ll focus on a specific set of steps to get things working without getting into too many of the behind-the-scenes technical details, the different philosophies on where static files can or should be placed, or the various and sundry ways in which this aspect of Django applications can be addressed.

Add a STATIC_ROOT Setting to the Django Settings File

First, your Django application’s settings file needs to include a STATIC_ROOT setting, and this setting is not in Django applications by default. The STATIC_ROOT setting is used when Django’s collectstatic management command is run to determine where to place the collected static files.
In our sample foo application, we’ll tell Django to collect the static files in a static directory located in the same directory as the settings.py file. (You can ultimately put your static directory wherever you wish, but this is where we’ll be putting it for the purposes of this example.)
To accomplish this, do the following:
  1. Using a plain text editor such as Notepad, or Idle if that was installed when you installed Python, open the file C:appsfoofoosettings.py
  2. Scroll to the bottom of the file, or use the find feature of your text editor, and find the STATIC_URL setting
  3. Above the STATIC_URL setting, add the following setting:
    STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, ‘foo’, ‘static’))
    1. The placement of the STATIC_ROOT setting in the settings.py file doesn’t matter, but putting it right next to the STATIC_URL setting is typical and keeps all the settings related to static files in one place.
    2. The STATIC_ROOT setting we’re using as our example will put the static files in C:appsfoofoostatic
  4. Save the settings.py file

Run the collectstatic Management Command

Now that Django knows where to put the static files, we can run the collectstatic management command. This command takes all the static files for your project, including the static files used by the Django admin and other packages in your virtual environment, and puts them under one static directory, the location of which is the STATIC_ROOT setting we added above, so they can be served by the web server.
  1. Open a Command Prompt
  2. Activate the application’s virtual environment:
    C:virtualenvsfooScriptsactivate.bat [then press Enter]
  3. Navigate to the application’s root directory:
    cd C:appsfoo [then press Enter]
  4. Run Django’s collectstatic management command:
    python manage.py collectstatic [then press Enter]
  5. Django will then tell you the directory into which it’s going to copy the static files, and ask you to confirm since this process overwrites any existing files in the directory. Type yes at this prompt and press Enter.
  6. The static files will then be copied to the directory indicated by the STATIC_ROOT setting.

Add a static Virtual Directory to the IIS Web Site

Now we have all our static files in one place, but we still haven’t told IIS where they’re located. We’ll accomplish this by adding a static virtual directory to the IIS web site for our application.
Note that the name of the virtual directory in IIS must match the value of the STATIC_URL setting in the Django application’s settings.py file, absent the beginning and trailing slashes. For our sample application we’re using a value of /static/ for the STATIC_URL setting, so the name of the virtual directory in IIS will be static.
Create a virtual directory in IIS as follows:
  1. Open IIS Manager
  2. On the left-hand side under “Connections,” expand the server’s tree
  3. Expand the “Sites” folder
  4. Expand the foo web site. At this point, things should look like this:
  5. Right-click the foo web site and click “Add Virtual Directory”
  6. In the Add Virtual Directory dialog, enter the following values:
    Alias: static
    Physical path: C:appsfoofoostatic
  7. Click “OK.” You’ll see the static virtual directory appear under the web site.

Configure Handler Mappings for the static Virtual Directory

The last step is to tell IIS which handler to use to serve files out of the static virtual directory. Since at this point our Django Handler is set to serve all files for our application, even with the static virtual directory in place the Django Handler will still be attempting to serve these files.
IIS already has a static file handler active in the web site, but it’s down further in the list of handlers than the global Django Handler we configured, so to get IIS to serve the static files under the static virtual directory we’ll move the static file handler to the top of the handler list on the static virtual directory.
  1. Open IIS Manager
  2. Expand the server tree
  3. Expand the foo web site
  4. Click on the static virtual directory
  5. Double-click the “Handler Mappings” icon. You’ll see the following list of handler mappings:
  6. On the right-hand side under “Actions” click on “View Ordered List …”
  7. You’ll now see a list of the handler mappings in the order in which they’re run, with the Django Handler at the top.
  8. Click on the StaticFile handler at the bottom of the list, then click “Move Up” under “Actions” on the right-hand side.
    1. Note at this point you may receive a warning that by moving handlers you are detaching this virtual directory from the inheritance of the parent’s handler mappings. This is what we want to do, so if you get this warning click “Yes.”
  9. Continue to click “Move Up” until the StaticFile handler is at the top of the list of Handler Mappings.
With the StaticFile handler at the top of the list of Handler Mappings, requests that come into the static directory will be handled by the StaticFile handler as opposed to being processed by the Django Handler, so IIS will serve the static files now.
Confirm that everything is working by going to http://localhost:81/admin in a browser. You should now see the CSS being applied to the page.

Additional Concerns with Static Files

  1. Don’t include the directory to which the STATIC_ROOT setting is pointing in your application’s code repository; these files should not be tracked and versioned from that location, and the Django development server handles static files for you by serving them directly from their various locations. The collectstatic management command should be run as a normal part of the deployment process for production instances of your application.
  2. For complete information about Django’s handling of static files, and production deployment of static files, please refer to the following section of the Django documentation:
    1. https://docs.djangoproject.com/en/1.9/howto/static-files/
    2. https://docs.djangoproject.com/en/1.9/howto/static-files/deployment/
At this point your Django application should be playing nicely with IIS.

Additional Information

The information in this section is merely for reference, and to retain some of the research that was performed in the preparation of this guide even though it ultimately may not have been used as part of the final configuration steps.

Resources/Further Reading

Interesting things I came across while preparing this guide, in no particular order:

Additional Avenues of Exploration

Install WFastCGI Gateway for IIS and Python 3.4

Installing WFastCGI for IIS through the IIS Manager is completely optional. It’s simply an alternate way of installing Python (in this case Python 3.4 specifically), and also provides the wfastcgi.py file that is required to configure a handler in IIS for Python applications.
If you perform these steps, Python 3.4 will be installed at the root of the C: drive, and this distribution of Python 3.4 will also place the wfastcgi.py file in the C:Python34 directory. You can then leverage this file or copy it into your application’s directory to configure the IIS handler.
  1. Open IIS Manager
  2. Click on the server in the list under “Connections” on the left-hand side
  3. At this point you may see a dialog box prompting you to install Microsoft Web Platform:
    1. If you see this dialog box, click “Yes.” This will open the download page in a web browser.
    2. If you do not see this box, under “Actions” on the right-hand side of IIS Manager, click on “Get New Web Platform Components.” This will open the download page in a web browser.
    3. You will be prompted to launch the Microsoft Web Platform application every time you launch IIS Manager, so if you see this dialog box after you have already installed the Web Platform Installer, feel free to check “Do not show this message” and then click “No.”
  4. On the Microsoft Web Platform web page, click the “Free Download” button.
  5. After the download completes, located the downloaded file and double-click to run it. As of the time of this writing the file is called wpilauncher.exe
  6. If you see a Security Warning dialog, click “Run” to run the installer.
  7. After the installation completes, the Web Platform Installer 5.0 application will launch.
  8. In the Web Platform Installer 5.0 application, in the search box on the top right, type “fastcgi” (without the quotes) and press Enter.
  9. In the search results, locate “WFastCGI 2.1 Gateway for IIS and Python 3.4” and click the “Add” button.
  10. At the bottom of the Web Platform Installer application, click “Install.”
  11. In the Prerequisites dialog that appears, click “I Accept” to accept the terms of the license.
  12. The WFastCGI extension will be downloaded and installed. When the installation completes, click “Finish” to close the installation dialog, and then click “Exit” to close the Web Platform Installer.
Note that doing installing the WFastCGI Gateway and Python 3.4 in this way does not automatically configure the FastCGI and Handler Mappings in IIS for you. It does install a default Python FastCGI application, but this will not necessarily automatically work with your application, and at a minimum you would still need to add a Handler Mapping for your application.

    82 thoughts on “Running a Django Application on Windows Server 2012 with IIS

    1. Hi Matt, thanks for a great and detailed tutorial!!
      However, I have encountered a problem when loading the page it returns "scriptProcessor could not be found in application configuration".

      After a lot of searching i've found this guide from Microsoft on Azure https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-windows-classic-python-django-web-app/

      Apart from not using virtualenv, the only difference is that they use the pyc version of the wfastcgi instead of py version like what you have… So I changed that and it works … Could you try again and if it's really because of that, maybe you can help update the tutorial. IIS gave no descriptive error at all, no clue to debug. (Just FYI, I was installing Django 1.9 on Windows Server 2012 R2)

    2. Thanks for this, it really helped me get this up and running. I would like to comment a few of the issues I noticed as I was going through the process.

      First off, I was using Windows Server 2008 R2 and can confirm it works on that version as well.

      In a few places, I had to change "wfastcgi.py" to "wfastcgi.exe". I'm not sure if perhaps I am using a different version of wfastcgi, but this was what my virtual environment installed.

      I also was having issues with Python 3.5.x but was able to resolve by using Python 3.4.3. I did this because of a statement from this Stack Overflow comment where they are also using Server 2008.

      http://stackoverflow.com/questions/42742324/python-exe-the-fastcgi-process-exited-unexpectedly

      If anyone would like to ask questions, feel free to also tweet at me @The42ndMatt

    3. Fantastic post on a tricky configuration.

      Got this working nicely by following these instructions unmodified for an app using:

      * Windows Server 2016
      * IIS 11 (I think, from memory).
      * Django 1.10.5
      * Python 3.6.

      Only gotcha I had to overcome – I had enum34 installed in the virtualenv – this broke wfastcgi.py (silently!). Problem identified by attempting to run the wfastcgi.py script directly (in the virtual env).

      Removing enum34 fixed the issue.

    4. Great guide! Thank you for sharing.

      I had to run wfastcgi-enable.exe in the virtualenvsfooscripts folder to "turn on wfastcgi 3.0.0" before it worked, but it's been working great now!

      Setup was
      • Windows Server 2008 R2
      • IIS 7
      • Django 1.9.8
      • Python 3.5

    5. Thanks for this. Ran thru the tutorial in about 1/2 an hour. Thought getting a Django app into production on a windows machine was going to be a lot of work.

    6. I followed up every step of your tutorial and I was able to setup my Django Website with IIS, but I would like to extend your steps a bit further because I found other problems that may appear once your web application is in the server. I am dividing my comment in two separate comments because the comment box is giving me some problems at trying to publish the text.

      Technical setup:
      Windows 10
      IIS 10
      Django 1.11.2
      Python 3.4.2

      First part
      In the last steps of the section Create and Configure a New IIS Web Site, you may encounter this error: python.exe: the fastcgi process exited unexpectedly or fastcgi process exited unexpectedly. What I did to solve this problem was to downgrade from python version 3.6.1 to 3.4.2. I had to repeat all the process of setup again but using the 3.4.2 python version.
      Next, in the same section you might see an error related to Allowed hosts , I do not exactly remember the full error, but in order to bypass it you need to add the IP address of your website that is mounted in IIS into the ALLOWED_HOSTS section that is found in the settings.py file of your Django application.

      Up to this point, the two described problems appeared to me before I could visualize the "Congratulations for deploying your first Django application…" message. The next set of problems appeared to me after I try to build a web application once Django was up and running in IIS. This is an optional reading but you might find it useful just in case you have ended up struggling to find out solutions to these problems.
      After Django was deployed in IIS I encountered a quite tricky error which is:

      Error occurred while reading WSGI handler: Traceback (most recent call last): File "C:virtualenvsnavigator6Libsite-packageswfastcgi.py", line 791, in main env, handler = read_wsgi_handler(response.physical_path) File "C:virtualenvsnavigator6Libsite-packageswfastcgi.py", line 633, in read_wsgi_handler handler = get_wsgi_handler(os.getenv("WSGI_HANDLER")) File "C:virtualenvsnavigator6Libsite-packageswfastcgi.py", line 605, in get_wsgi_handler handler = handler() File "C:virtualenvsnavigator6libsite-packagesdjangocorewsgi.py", line 13, in get_wsgi_application django.setup(set_prefix=False) File "C:virtualenvsnavigator6libsite-packagesdjango__init__.py", line 27, in setup apps.populate(settings.INSTALLED_APPS) File "C:virtualenvsnavigator6libsite-packagesdjangoappsregistry.py", line 78, in populate raise RuntimeError("populate() isn't reentrant") RuntimeError: populate() isn't reentrant StdOut: StdErr:

      What the error is trying to indicate you is that a library which is required by your settings.py file was not installed. In my case, I have added the rest_framework APP in the settings.py file but I forgot to install the djangorestframework library. I did the following to solve this problem:

      py -m pip install –upgrade wheel
      py -m pip install wfastcgi
      py -m pip install djangorestframework

      Notice that everything should be installed inside of the virtual environment.

    7. Second part

      After this error was solved I was able to visualize and navigate through the web pages that I have built, but when I try to do some scripting with AJAX I found out a difficult error to track down: 500 internal server error: The FastCGI process exceeded configured activity timeout.
      Module FastCgiModule
      Notification ExecuteRequestHandler
      Handler Django Handler Navigator
      Error Code 0x80070102

      This error means that your website made a request to the server but there was no response from the server due to a timeout error connection. To solve this you need to increase the activity timeout settings by doing the following:

      At server level not default web site or your website:

      Double click FastCGI Settings
      Open your Django handler that you defined at the beginning of this guide.
      Click on Edit button and change the Activity Timeout settings. The default Timeout is 60 (seconds) but I changed it to 600 (which is 10 minutes).

      After this last change, I was able to perform AJAX requests.

      Hope these last comments help everyone so you avoid spending fixing these technical problems.

    8. @Matt Mitchell — sounds like that's just an issue with your hosts file and/or your IIS bindings. If you add the full domain as a binding and add the domain and IP to the calling machine's hosts file (or do real DNS for it) that should fix it.

      Or if by "not working" you mean you get a bad request error you may just need to add the full domain to your ALLOWED_HOSTS setting if you have Debug set to False.

      Hope that helps.

    9. Just wanna say thank you to Matt for this guide. I am able to make django works with IIS with little to no difficulty. I am a beginner web developer and trying to make this work to have my data visualization dashboard. With my current vanilla knowledge of networking and web serving, not sure if I am able to fully comprehend everything in this guide nor will I be able to discover it on my own. But following it does work so, great guide!

      Here is my system stats:
      – Microsoft Windows 10
      – IIS version 10.0.14393.0
      – Python 3.6
      – Django 1.11.3
      – virtualenv 15.1.0
      – wfastcgi 3.0.0

    10. As you might imagine security is a topic in and of itself, but yes, provided your server itself is patched and configured securely, this setup is no less secure than any other Django application would be out of the box.

    11. I even tried mapping the handler, but I get the following error: Contact Us
      >>>>grammar0526@naver.com

      Error occurred while reading WSGI handler: Traceback (most recent call last): File "C:virtualenvsfooLibsite-packageswfastcgi.py", line 791, in main env, handler = read_wsgi_handler(response.physical_path) File "C:virtualenvsfooLibsite-packageswfastcgi.py", line 633, in read_wsgi_handler handler = get_wsgi_handler(os.getenv("WSGI_HANDLER")) File "C:virtualenvsfooLibsite-packageswfastcgi.py", line 603, in get_wsgi_handler handler = getattr(handler, name) AttributeError: module 'django.core.wsgi' has no attribute 'get_wsgi_application () ' StdOut: StdErr:

    12. Just tested this tutorial, worked like a charm!

      – Windows Server 2016
      – Python 3.6.2
      – 1.11.5
      – wfastcgi 3.0.0

      Can confirm that all steps to be taken are similar to this guide wich is written for 2012R2

    13. Hello, i hope you can help me… I followed your tutorial and Its worked! Thank you!

      I can access to the url in other computers, but I don't know why the cx_oracle is failing, the error is: "Oracle client cannot be loaded: the specified module could not be found"

      The application worked in my local host using manage.py runserver, but IIS throw me an error when I tried to do a request =(

    14. Sounds like you're missing the Python Oracle package, either that or it's installed and the configuration isn't quite right. I haven't done anything with cx_Oracle on Windows, but have gotten it working on Linux in the past (with a bit of effort). First thing to verify is that it's installed — check that and we'll take it from there if it still isn't working.

    15. Great blog! I was able to complete all the steps. Expect the last step didn't work. I ran python manage.py collectstatic and it moved the files as it should. Then I restarted IIS and the site then tried to load the page. http://localhost:81/admin/ this worked but the CSS is still not being applied to the site. I can see the the link rel="stylesheet" type="text/css" href="/static/admin/css/base.css" in the view source. Any suggestions?

    16. @Christopher — the first thing that comes to mind is maybe you didn't add the virtual directory for static in the IIS settings? Give that a shot and let me know if that was it. The only other thing I can think is maybe a permissions issue. Are you getting a 404 for your CSS file or some other error?

    17. Great and helpful post Matt.
      Your instructions are very very clear!
      I got the 'ScriptProcessor…' error (mentioned in the first comment). In my case it was due to a space after the 'pipe' symbol in the Handler's Module Mapping.

      I did a simple django app with one view and sqlite.
      Hopefully it will scale with larger app and postgre.

      Windows OS 10
      IIS Version 10
      Django 2.0.1
      DRF
      Vue2 – not using templates – just for capturing events
      Vue-resource
      material css

    18. I've gone through this tutorial using Python 2.7.x. Except a couple of small hiccups (virtualenv instead of venv and such) it worked perfectly.
      Thanks!

      I do have a problem with authentication.
      The default Django authentication works fine. However when using LDAP auth IIS doesn't seem to know there is a logged in user.
      I am still debugging the problem – I found that there is no entry in django_sessions table (there is for a local admin).

      Have you encounter this problem?
      Any idea what configuration is missing?

    19. Thanks for that awesome tutorial!

      It works with Python 3.6.4 and Django 2.0.2.

      Now, I'm struggling to get several windows environment variables for SECRET_KEY, DB_USER etc. in the settings.py file.

      For example I have:

      Windows user environment variable: DJANGO_SECRET_KEY=[SecretKey]

      In settings.py: SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')

      But I get an error message, that SECRET_KEY setting must not be empty.

      I think, it's because of the virtual environment, but how can I fix that or where do I have to correctly put these variables?

    20. …okay, I set these variables like the other three variables (DJANGO_SETTING_MODULE, PYTHONPATH, WSGI_HANDLER) from section

      Configure FastCGI in IIS

      => step 14.

      Is that the correct way to do?

    21. @binaryecon — if you're using environment variables then yes you could do it that way, or in your Django project you could use something like django-environ and handle things that way.

    22. Matt, buddy you made such fantastic instructions which have been a blessing to my payroll django project on Windows. Apache is easy to setup on Linux but on Windows IIS is the best solution for a webserver. You have an eye for detail, just like me, and that is why your blog was one of the best I have ever read. Keep doing such a great job man. You are helping tech humanity globally. I am from New Delhi, India.
      Ciao

      regards
      Alok Gupta

    23. Thanks so much, I got this going with Python 3.6 & Django 2.

      For anyone who has IIS Manager but not the CGI component: Go to Control Panel >Programs and Features >Turn Windows features on or off. Expand Internet Information Services, expand WWW Services, expand Application Development Features. Click CGI >OK.

      I also needed to add and allow security permissions for this user on the app folder & the venv folder: IIS_IUSRS. That made 500 errors go away.

    24. Thanks for this great detailed tutorial Matt. However I've run into some issues.Can you please help me out. Everything installed fine and when I run using django server on localhost the admin page opens up fine but if I try to access it remotely or even locally via IIS I get following 404 error :

      "Using the URLconf defined in foo.urls, Django tried these URL patterns, in this order:

      admin/
      The current path, foo, didn't match any of these."

      This is my directory structure

      foo
      ├── manage.py
      ├── web.config
      ├── _foo
      | ├── settings.py
      | └── urls.py
      | └── wsgi.py
      | └──__init__.py
      | └── static
      | ├── admin
      | | ├───css
      | | └── fonts
      | | └── img
      | | └── js
      | └── web.config

      my foo project webconfig file(replaced '<' '>' with '(' ')' for this comment)

      (configuration)
      (system.webServer)
      (handlers)
      (add name="Django Handler" path="*" verb="*" modules="FastCgiModule"
      scriptProcessor="D:Python_venvsfooScriptspython.exe|D:Python_venvsfooLibsite-packageswfastcgi.py"
      resourceType="Unspecified"
      requireAccess="Script" /)
      (/handlers)
      (/system.webServer)

      (appSettings)
      (add key="WSGI_HANDLER" value="django.core.wsgi.get_wsgi_application()" /)
      (add key="PYTHONPATH" value="D:wwwrootappsfoo" /)
      (add key="DJANGO_SETTINGS_MODULE" value="foo.settings" /)

      (/appSettings)
      (/configuration)

      Technical setup:
      Windows Server 2012
      IIS 8
      Django 2.0.5
      Python 3.6.5

      One thing I have done differently than you is instead of instead of making a new website in IIS Manager,I just added 'foo' as a web application in an existing website.

      Can you please help me out

    25. I added logging to my settings.py and set it at DEBUG level. This is the output im getting

      "2018-06-11 17:42:19,210 django.template DEBUG Exception while resolving variable 'name' in template 'unknown'.
      Traceback (most recent call last):
      File "D:Python_venvsfoolibsite-packagesdjangocorehandlersexception.py", line 35, in inner
      response = get_response(request)
      File "D:Python_venvsfoolibsite-packagesdjangocorehandlersbase.py", line 113, in _get_response
      resolver_match = resolver.resolve(request.path_info)
      File "D:Python_venvsfoolibsite-packagesdjangourlsresolvers.py", line 523, in resolve
      raise Resolver404({'tried': tried, 'path': new_path})
      django.urls.exceptions.Resolver404: {'tried': [[ (admin:admin) 'admin/'>]], 'path': 'foo/'}

      During handling of the above exception, another exception occurred:

      Traceback (most recent call last):
      File "D:Python_venvsfoolibsite-packagesdjangotemplatebase.py", line 835, in _resolve_lookup
      current = current[bit]
      TypeError: 'URLResolver' object is not subscriptable

      During handling of the above exception, another exception occurred:

      Traceback (most recent call last):
      File "D:Python_venvsfoolibsite-packagesdjangotemplatebase.py", line 843, in _resolve_lookup
      current = getattr(current, bit)
      AttributeError: 'URLResolver' object has no attribute 'name'

      During handling of the above exception, another exception occurred:

      Traceback (most recent call last):
      File "D:Python_venvsfoolibsite-packagesdjangotemplatebase.py", line 849, in _resolve_lookup
      current = current[int(bit)]
      ValueError: invalid literal for int() with base 10: 'name'

      During handling of the above exception, another exception occurred:

      Traceback (most recent call last):
      File "D:Python_venvsfoolibsite-packagesdjangotemplatebase.py", line 856, in _resolve_lookup
      (bit, current)) # missing attribute
      django.template.base.VariableDoesNotExist: Failed lookup for key [name] in (admin:admin) 'admin/'>

      2018-06-11 17:42:19,213 django.request WARNING Not Found: /foo/"

    26. Hi Umar — based on an admittedly cursory reading my first guess is that you added things under an existing website as opposed to as its own site, since everything I did was based on the Django app being at the root of the site. I'll try to take a run at doing things this way when I get a chance and see what I can figure out.

    27. Thanks @Alok but I already had __init__ in my project and application folders.

      @Matt -You are absolutely correct.Once I changed the path in URLPATTERNS from

      path('admin/', admin.site.urls)

      TO

      path('foo/admin/', admin.site.urls)

      It now works as desired.

      I guess I need to study Djangos URL routing in more depth because as I understood it before,I thought the apps within the Django project were relative to the to the URL specified in IIS..In my case

      https://somewebsite.com/foo would route to the root of the django project and then from there specifying paths like :


      path('anyappfolder/',include('anyappfolder.urls')),
      path('admin/', admin.site.urls)

      would route to them.

      But now the way I see it…When the user goes to
      https://somewebsite.com/foo

      The path needs to be specified as
      path('foo/anyappfolder/',include('anyappfolder.urls')),
      path('foo/admin/', admin.site.urls)

      to access those pages/apps. I dont understand why foo has to be specified twice.

      Thanks for your help 🙂

    28. Hey Matt, awesome tutorial! Way better than compiling mod-wsgi on Windows

      Had a question on logging though. Do you know how the stdout etc is configured to integrate with IIS logging?

    29. I am getting
      Config Error Cannot read configuration file due to insufficient permissions
      Config File \?C:Userschinmay_arimaresolution_validatorweb.config
      this error. My Django version is 2.2 and IIS 8.

    30. Thanks so much Matt! I've been patiently waiting for someone to post a great tutorial like this one. I needed this to get me started with Django. Truthfully there's not a lot of good tutorials for us Windows 10 users. This tutorial got me up and running without a single mistake. Now., I am happy as I've managed to install tensorflow-gpu natively without Anaconda and etc., and to top it off -a win webserver thanks to you! I know that was off topic, so pls excuse me. 🙂 It's just that, I wished other tutorials were written as concise as yours! Thanks again and great work!

    31. "Thanks for this tutorial!

      I was able to follow until the very last steps of Create and Configure a New IIS Web Site. I'm running into a 500.0 error page: The FastCGI process exited unexpectedly.

      Setup:
      Windows Server 2012 R2
      IIS 8.5
      Python 3.7.1
      Django 2.1.3
      wfastcgi 3.0.0

      I tried modifying envLibsite-packageswfastcgi.py directly to create a file called 'test_log.txt' as the first executed line, and it appears not to be running when i start/stop the server and/or site. I can run the wfastcgi.py file with python directly and it will create the file, so i suspect there's something going wrong between IIS getting the request and passing it to Django.

      I'm able to start the dev server with no issue via manage.py runserver, and i've triple checked my environment variables/handlers/mappings. I checked permissions for {server name}IIS_USRS, and they have read/read&execute access, and i tried granting write access just to see, but no dice.

      Any advice where to look next to debug?"

      I'm having exactly the same issue on Windows Server 2016

    32. @Sinterklaas:

      Seems like a permissions issue. I was able to get the site to run by changing the AppPool user account from AppPoolIdentity to an administrator account. Haven't been able to add permissions to the proper AppPool User to get it to run, think it has to do with the cgi.exe being in C:WindowsSystem32inetserve, which is locked down.

    33. Thanks Matt for creating great instruction. Also thanks all of the commenters for valuable additional information.

      @Unknown and @Sinterklaas: Thanks for your finding. It helped me found a way to workaround the authentication issue. I used Windows 10's SettingAccounts to create a normal user with a password, then set application pool identity (IIS Manager > Server > Application Pools > my app pool > Advanced Settings > Process Model > Identity > Custom Account > Set). This way we don't have to use administrative account for the application. Of course we also need to set permission for the user to access application folder. FYI I used old way to create user (right click computer > Manage > Users) but the error was still there, until I used the new way above.

    34. More information on the "The FastCGI process exited unexpectedly" issue.

      Windows 10 + built-in IIS + Python 3.7.1 + Django 2.0 + User account for App Pool Identity –> Working
      Windows 8 + built-in IIS + Python 3.7.1 + Django 2.0 + User account for App Pool Identity –> Not working
      Windows 8 + built-in IIS + Python 3.7.1 + Django 2.0 + Admin account for App Pool Identity –> Not working
      Windows 8 + built-in IIS + Python 3.4.4 + Django 2.0 + User account for App Pool Identity –> Not working
      Windows 8 + built-in IIS + Python 3.4.4 + Django 2.0 + Admin account for App Pool Identity –> Not working

    35. I am using windows server 2016, I am able to run my Django app on the global python. But when I try to change it to run it with the virtualenv I get "HTTP Error 500.0 – Internal Server Error c:virtualenvtestscriptspython.exe – The FastCGI process exited unexpectedly"
      I gave IIS AppPooltest permissions to the python virtual env folder c:virtualenvtest. but still getting this error does anyone have a clue? does it have to do with the app pool?

    36. We found two reasons that causes this problem:
      1. Forgot to install wfastcgi
      2. Forgot to select the option "Customize installation", then check the checkbox "Install for all Users".

    37. Just wanted to say thanks for the blog, very helpful getting Django pushed out through IIS. The only stumbling block I hit was permissions for the AppPool identity but once that was sorted the site ran fine.

      Windows 10
      IIS 10
      Python 3.7.0
      Django 2.1.1
      MySQL 8

      Multi application package and all works perfectly 🙂

      1. please can you tell me how did you do this :
        The FastCGI process exited unexpectedly can you please tell me in detail thank you

    38. Hi there awesome tutorial this has been really helpful in setting up and connecting Django to windows server
      my only issue is the iis server is not seeing my static files for my html templates its only serving the one for admin I have tried adding the folder to the iis manager like in the tutorial but its still not serving the static files …but the my development server is seeing the static files

    39. I successfully did this and now running my Django apps in the windows server.

      My question after doing this how can I host another normal HTML website using IIS in the same server?

    40. Hello,
      I followed all the steps, however, i get the following error at the end when i try to browse localhost:81/
      HTTP Error 500.0 – Internal Server Error
      scriptProcessor could not be found in application configuration
      Any advice where I am making mistake.
      Thanks

    41. I’m trying to deploy two django application on separate port on IIS but it’s not work.

      Only first hosted application is running, while deploying 2nd giving 500 error wfastcgi.

      I set IIS user permission for python.exe directory

    42. First of all I would like to say thank you for this tutorial. I have deployed my django project on IIS . I didn’t get any error while deployment but am unable to load my website on browser. Can you pls help me on this

    43. Thank you Matt for your job.
      when I got to the point:
      Open a browser on the server
      Browse to http://localhost:81

      I have following problem:

      Detailed Error Information:
      Module FastCgiModule
      Notification ExecuteRequestHandler
      Handler Django Handler
      Error Code 0x00000067
      Requested URL http://localhost:80/
      Physical Path C:\drmproject1\drmproject1
      Logon Method Anonymous
      Logon User Anonymous

      I have searched a solution, but unsuccessful.

    44. Hi Rauan, I haven’t messed with this stuff in quite a while but the first thing that jumps out oat me is the error message shows the requested port is port 80 instead of port 81, so maybe see what might be going on with your port bindings for the site?

    Leave a Reply

    Your email address will not be published. Required fields are marked *