18. Deploy Project into Windows Server (IIS)#
18.1. Prepare Python env and IIS#
18.1.1. Python Environment Setting#
According to author’s experience,
python 3.9.x
is not compatible withFastCGI
, therefore we need to re-create a conda env withpython==3.8
And then, we need reinstall the required library, in a case you do not generate
requirements.txt
, we do it one by one herewfastcgi
provides a bridge between IIS and Python using WSGI and FastCGIconda create -n py38 python==3.8 conda activate py38 pip install django pip install django-allauth pip install django-crispy-forms pip install crispy-bootstrap4 pip install jwt pip install et-xmlfile pip install requests pip install urllib3 pip install wfastcgi pip install pillow
18.1.2. Django Project Setting#
Remember to change Debug model to
False
and add Host IP into yourdjango_project.settings.py
Set
STATIC_URL
,STATIC_ROOT
,MEDIA_URL
,MEDIA_ROOT
Don’t put any static files in the
STATIC_ROOT
directory. That’s where the static files get copied to automatically after you runcollectstatic
.Instead, always put them in the directories associated with the
STATICFILES_DIRS
setting or<APP_NAME>/static/
.#django_project.settings.py ... DEBUG = False ALLOWED_HOSTS = ['*'] ... STATIC_URL = "static/" MEDIA_URL = '/media/' STATIC_ROOT = os.path.join(BASE_DIR,'static') MEDIA_ROOT = os.path.join(BASE_DIR,'media') ...
18.1.3. Install IIS#
Search Turn Windows features on or off, check
Internet Information Services
andInternet Information Services Hostable Web Core
Goto
Internet Information Services
>World Wide Web Services
>Application Development Features
, CheckCGI
Click
OK
to apply this setting, and restart your machine to activate it.
18.1.4. Verify the IIS Installation#
Open a web browser on the server, goto http://localhost/.You should see the default IIS page.
18.2. Configure IIS#
18.2.1. Option 1: Configure FastCGI using IIS#
Click on the name of the server in the list on the left. Double-click the
FastCGI Settings
iconUnder
Actions
on the right-hand side clickAdd application …
In the Add FastCGI Application dialog, in the
Full Path
box, type the path to the Python env we just created, and In theArguments
input box, type the path to thewfastcgi.py
file in thesite-packages
Under the
General
section, click on theEnvironment Variables
line, then click the gray…
button that appears next to (Collection) on the right-hand side of the line.Add
DJANGO_SETTINGS_MODULE
with value{Your_Django_Project_name}.settings
Add
PYTHONPATH
with value{Your_Django_Project_Path}
Add
WSGI_HANDLER
with value{Your_Django_Project_name}.wsgi.application
18.3. Create and Configure a New IIS Web Site#
Next, we need to create a new website in IIS for the Django application and add a Handler Mapping to the newly created website so that requests coming to the IIS website are passed off to the Django application for processing.
18.3.1. Create a new Web Site#
Open
IIS Manager
, Right-click on theSites
folder and clickAdd Website …
For the
site
, name the project as you want. For thephysical path
, type the path to the project. ClickOK
.
18.3.2. Option 1: Set FastCGI Handler using IIS#
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.
In
IIS Manager
, expand the Sites folder on the left-hand side and click on thesite
. On the right, double-clickHandler Mappings
On the right, under
Actions,
clickAdd Module Mapping
Fill out the form using your data
D:\Anaconda3\envs\py38\python.exe|D:\Anaconda3\envs\py38\Lib\site-packages\wfastcgi.py
Click the
Request Restrictions
button and uncheck theInvoke handler only if the request is mapped to
checkbox
18.3.3. Option 2: Set FastCGI Handler using web.config
#
Build a
web.config
at under the same dir of{Your Django Project}
, below is myweb.config
file<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <handlers> <add name="Python FastCGI" path="*" verb="*" modules="FastCgiModule" scriptProcessor="D:\Anaconda3\envs\py38\python.exe|D:\Anaconda3\envs\py38\Lib\site-packages\wfastcgi.py" resourceType="Unspecified" requireAccess="Script" /> </handlers> </system.webServer> <appSettings> <add key="WSGI_HANDLER" value="django.core.wsgi.get_wsgi_application()" /> <add key="DJANGO_SETTINGS_MODULE" value="django_project.settings" /> <add key="PYTHONPATH" value="E:\2024\github\django-blog-project\django_project" /> </appSettings> </configuration>
18.4. Load Static and Media file properly#
18.4.1. Gather all static files and make a static virtual path#
run
python manage.py collectstatic
under your django projectIt will generate
admin
under yourstatic
path, which contains all static files
Add Virtual Directory
in your siteFill the form using your
static
infoPut a
web.config
under yourstatic
folder<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <handlers> <clear /> <add name="StaticFile" path="*" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" /> </handlers> </system.webServer> </configuration>
18.4.2. Do the same for media
#
18.5. Check Result and Set Firewall#
18.5.1. Check Result#
At this point everything should be working, so verify by loading the application in a browser.
Open a browser on the server, Browse to
http://localhost:{port number you set}
18.5.2. Configure the Windows Firewall#
18.6. Possible Error#
18.6.1. Python env issue#
Error occurred while reading WSGI handler:
Traceback (most recent call last):
...
File "D:\Anaconda3\envs\py38\lib\site-packages\django\apps\registry.py", line 83, in populate
raise RuntimeError("populate() isn't reentrant")
RuntimeError: populate() isn't reentrant
StdOut:
StdErr:
open
django/apps/registry.py
, and around line 80, replace:raise RuntimeError("populate() isn't reentrant")
withself.app_configs = {}
This will allow Django to continue loading, and reveal the actual error.