Docker on Windows 10: Sharing a Drive When Logging in With a Microsoft Account

If you’re using Windows 10 and you log into your computer with a Microsoft account, meaning you use an email address that’s associated with a Microsoft account as opposed to a local account on the computer itself, you may have run into the oft-reported issue of sharing your C drive with Docker. Without sharing the C drive, Docker basically can’t work properly.

The root of the problem is that when you log in with a Microsoft account it doesn’t have a password stored on the local machine, so when Docker asks you to enter your username and password to authorize the drive sharing, there is no password for you to enter, and Docker doesn’t let you leave it blank.

There are a lot of suggestions on the interwebs but to hopefully save others some time, this is the only way to solve this problem I found to work.

Create a New Local User Account

  1. Hit the Windows key, type “Settings,” and click on the Settings app
  2. Click “Accounts”
  3. Under “Other Users” click “Add someone else to this PC”
  4. On the “How will this person sign in?” dialog, click the “I don’t have this person’s sign-in information” link at the bottom
  5. On the “Create account” dialog, click “Add a user without a Microsoft account”
  6. Enter a user name and password, set your security questions and answers, and click “Next”

Change the Account Type of the New Account to Administrator

  1. Click on the newly created account name
  2. Click “Change account type”
  3. Click the “Standard User” drop-down and select “Administrator”
  4. Click “OK”

Log In as the New Account and Grant It Access to Your User’s Directory

In order for the new account to work correctly in the context of Docker, you have to log in under the new account and give the account full permissions on your user’s directory, or whatever directory you want Docker to be able to access to read/write/delete files.

  1. Click Ctrl-Alt-Del and click “Switch user”
  2. Click on the newly created user account
  3. Log in with the user name and password
  4. After the initial setup process completes, go to Windows Explorer and navigate to your user’s home directory (e.g. C:\Users\me) and click on it.
  5. You’ll get a message indicating that the new user doesn’t have access to that folder. Click Continue to grant the user access to the folder.
  6. When the permissions setting process completes, log out of the local user account and switch back to your own user’s account.

Enable Drive Sharing in Docker

  1. In the taskbar, right click the Docker icon and choose “Settings”
  2. Click “Shared Drives”
  3. Check the box next to the C drive and click “Apply”
  4. Enter the user name and password for the new local account you created above

At that point Docker should be happy. Hopefully in a future release Docker will support Microsoft accounts directly.

Year-End Contribution Summary Letters in CiviCRM

Wow. It’s been a year and a half since I’ve written any blog posts so I guess it’s about time.

General catchup: slightly new job at the US Senate Sergeant at Arms with slightly different responsibilities, and I’m still doing and loving Python, Django, and Postgres.

On the volunteer work front, I’ve been doing quite a lot with CiviCRM over the past year and I’m really enjoying it. The application itself is great and the community is friendly, helpful, and all-around fabulous. It’s everything an open source project should be.

In the spirit of giving back, I figured now that I have a decent handle on a thing or two I’d start sharing a bit of what I’m learning and doing with CiviCRM.

For this installment, I’ll cover how to do year-end contribution summary letters, which is relatively simple but there’s a couple of wrinkles I thought might help others, or if nothing else will help me next year when I have to do this again.

The Task

One organization I do CiviCRM work for is the wonderful Port Townsend, WA non-profit community radio station KPTZ. Since we’re a 501(c)(3) donations to the station are tax deductible, so for tax purposes we need to send out a letter to each donor with their total contributions for the previous calendar year.

For context, I’m using CiviCRM 5.9.0 on WordPress 5.0.3.

Step One: Enable Smarty in Mail Templates

It turns out there’s a variable you can access in mail templates to total up the contributions by donor, but it only works if you enable the ability to use the PHP template engine Smarty in CiviCRM’s mail templates, and this is disabled by default. (Thanks to Demerit on the CiviCRM StackExchange for pointing out my oversight on this!)

  1. ssh into your server
  2. Open the file [wordpress-root]/wp-content/uploads/civicrm/civicrm.settings.php in an editor
  3. Locate the following line and change 0 to 1:
    define( ‘CIVICRM_MAIL_SMARTY’, 1 );
  4. Save the file

Step Two: Create Your Mail Template

One of the many great features of CiviCRM is the fantastic, flexible mail templating system, and as we’ll see in a bit once you create a template it can email people with email addresses and use the same template to generate PDFs for contacts who don’t have email addresses.

  1. Log into CiviCRM
  2. Go to Administer -> Communications -> Message Templates
  3. Click “Add Message Template”
  4. Give your message a title and subject
  5. In the HTML Format section you’ll enter your letter, which of course will contain the text you want. To output the total contributions for a donor for the year, you’ll use the template token {$contribution_aggregate}, so you can have something like this in your letter:
    Your total donations for 2018 were {$contribution_aggregate}
  6. Another tip: with Smarty enabled, you can also add the current date to your letter much more easily than without Smarty:
  7. Although most everyone can deal with HTML email just fine these days, it’s still best practice to include a plain text version of HTML emails, so be sure and copy your letter from the HTML Format box into the Plan-Text Format box
  8. Click “Save and Done” to save your template

A really quick aside on the Smarty date_format filter — in the context of the WYSIWYG editor doing a custom date format (e.g. date_format:”%B %e, %Y”) will blow things up because the quotes get turned into HTML entities by the WYSIWYG editor. You can get away with this in source view, but if you ever change back to WYSIWYG mode it’ll break things again. For my case the default date format was just fine.

Step Three: Find Your Contributions

Next we’ll want to locate the contributions for which you want to send the summary letter, which in my case I did as follows (obviously update this as needed for your use case):

  1. Contributions -> Find Contributions
  2. Search Criteria:
    1. Date Received; Previous calendar year
    2. Financial Type: Donation
    3. Contribution Status: Completed
  3. Click “Search”

From the search results you can pick and choose the donations you want to include; in my case I want all the donations for the previous calendar year so I do the following:

  1. Click the radio button to select all the records returned
  2. Click the Actions drop-down and select “Thank-you letters – print or email”

Step Four: Email/Generate Thank-You Letters

Now for the easy part! At this point all we need to do is select a couple of options and use the template we created above.

Thank-you Letter Options

  1. Set “Update thank-you dates” and “Update receipt dates” as you wish
  2. Group contributions by: Contact
  3. Separator: this is the separator you want to use for the contribution-related tokens if you’re going to output each individual contribution in your letter. This doesn’t matter for my use case since I’m not including the individual contributions, but set this as needed for your letter.
  4. Print and email options: For testing purposes you’ll probably want to choose “Generate PDFs for printing (only)” so you don’t inadvertently send out any emails before you’re sure everything’s working, and then once everything looks good I tend to use the “Send emails where possible. Generate printable PDFs for contacts who cannot receive email.”
  5. From Email Address: pick the appropriate from email for your letter

In the “Use template” drop-down, select the template you created in Step Two above. You’ll see the Document Body populate (and you can tweak your template for this specific mailing at this point) as well as the Activity Subject.

If everything looks good, click the “Make Thank-you Letters” button to generate the PDFs. Verify everything is correct, and then send out the actual emails and letters.

That’s it! Pretty simple, and after you’ve set this up once you’ll be all set for next year.

I hope some of you other CiviCRM newbies found this useful. I hope to write more about CiviCRM soon. Thanks for reading.

How to Back Up Google Drive to a Raspberry Pi

Yes, you read that direction correctly: this is a how to covering backing Google Drive up to a Raspberry Pi, not the other way around.

For the impatient, here’s a link to the scripts on GitHub, but it’ll probably help put things in context if you at least skim the rest of this post since there are a couple of dependencies in the mix.


I do volunteer tech work for an organization that, like many organizations, uses Google Drive heavily, and doesn’t have much money to throw around. This organization’s Tech Committee has discussed whether or not we need to have a backup of the Google Drive files numerous times, but we keep kicking the can down the road since Google Drive versions files and retains trash until someone empties it, lessening the necessity of having a backup.

But, catastrophes happen. If someone were to delete all the files and empty the trash, you do have 25 days to contact Google and they can try to get your files back for you. Alternatively, you could hope someone has a copy of everything on their local machine. I’m sure some folks do, me being one, but crossing one’s fingers does not a good backup policy make, and if someone is frantically looking for a file, I’m not sure I want to have to contact Google to hunt it down. Plus this seemed like a fun little project.

Another alternative if you want to spend some money would be to use one of the services that will backup Google Drive to another cloud storage. In my situation we didn’t want to spend any budget on this, and we didn’t want to make it a task someone had to remember to do manually. Since I have a few Raspberry Pis laying around I decided to take a run at coming up with a solution I could just have running quietly in my house that would cover us in the event of a disaster.

Requirements and Constraints

The requirements/constraints I placed on myself were as follows:

  1. It can’t cost any money other than the cost of the Raspberry Pi and SD card. (And since I have several I’m not using, this was “free.”) I do cheat just a hair on this point in a couple different ways; see below.
  2. It can’t take me an inordinate amount of time to set up since I have a million things to do. So while digging into the Google Drive API and rolling my own solution from scratch sounds like fun, now isn’t the time for me to do that, so I was looking for solutions that will do as much of the work for me as possible.
  3. Since the Raspberry Pi is going to be sitting on a shelf somewhere not hooked up to a monitor, I’ll need some sort of notification that the backup worked, so if I don’t get notified I’ll know something’s up. This doesn’t need to be fancy, I just need to know it’s working.
  4. This is a last resort backup, so I’m not going to be doing any fancy file versioning or anything along those lines. The sole intent for this is to have a backup of the files if none exists anywhere else.

Step One: Configure the Raspberry Pi

Since I hadn’t messed with Raspberry Pis in a while and wasn’t sure what state the operating systems on the ones I have were in, I just grabbed one with a 64GB SD card and started from scratch.
  1. Download and install Etcher if you don’t already have a program you use to write images to SD cards
  2. Download Raspbian
  3. Use Etcher to write the Raspbian to the SD card
  4. Stick the SD card in the Raspberry Pi and boot it up
This should get you to a desktop. (If you don’t have a monitor, keyboard, and mouse and need to launch headless, you can read about how to to that here.)
Next, we’ll want to install some updates and configure the Pi.
  1. Open a terminal
  2. sudo apt update && sudo apt upgrade
  3. sudo raspi-config
    1. You can change whatever settings you want here (root password, etc.), but the critical one is to make sure the clock sets from the network on boot, so …
      1. Select “Localisation Options”
      2. Change Locale as appropriate
      3. Select “Change Timezone” and set your timezone
    2. You’ll also likely want to go to “Advanced Options” and select “Expand Filesystem” so the OS will use your whole SD card (I’m not using an external hard drive in my setup; I just stuck a 64GB SD card in there which will be plenty to backup what I need)
    3. I had to change my keyboard layout from the default British layout to American; if you try to type an @ and see # instead, that’s a telltale sign you’re in the same boat.
    4. Since I may have multiple Raspberry Pis on my network soon I changed the hostname to something specific to this task.
    5. Choose “Update” to update the config tool to the latest version
  4. Reboot the Pi

Install and Configure overGrive

This is where I cheated one of my constraints but met another. overGrive is a Google Drive client for Linux, and since Google doesn’t officially support one anymore, this one cost $5. That said, this also saved my tons of time so I met that aspect of my goals, and I don’t mind at all supporting people who build useful tools such as this.

Basically what the solution winds up being is I’ll use overGrive to sync the specific folder from Google Drive I want to back up, and then I’ll use good ol’ rsync to copy the files to another directory, thereby having a backup of what’s on Google Drive no matter what someone does to the files online.

Basically all you need to to for this step is follow the installation instructions here. It worked without a hitch for me.

Once overGrive is installed, do the following:

  1. Click on the Raspberry menu, then “Accessories,” then “overGrive”
  2. Click “OK” on the “Setup Required” screen
  3. Click “Connect account” — this will open up a Google login screen in a browser
  4. Log in with the Google account that has access to the Google Drive you want to back up. NOTE: overGrive does not seem to support “Shared With Me” Google Drive folders, so you’ll want to use the Google account that owns the files you want to back up.
  5. Accept the overGrive permissions
  6. Copy the code on the screen that reads “Please copy this code, switch to our application and paste it there”
  7. Switch back to the overGrive settings application
  8. Paste the code into the “Copy and paste the Google Drive Authentication code here” box
  9. Click “Validate”
  10. Click “Activate” if you bought an overGrive code, or click “Continue” if you want to try it out free for 14 days
  11. At this point you’re back on the “Setup Step 2 of 3” screen. Here, since I only want to back up one folder, I clicked the “Only sync certain folders to this computer” option and chose the folder I want to back up.
  12. Make sure “Auto Sync” is checked so overGrive will automatically stay in sync with changes on Google Drive.
  13. Click “Start Sync.” This will, as the button says, start the files syncing. According to the overGrive documentation it’s important that you let this finish so if you have a lot of files, this might be a good time to call it a night and check on things in the morning, when we’ll deal with the script to do the actual backup and send notifications.

The Backup and Archive Scripts

The “backup” concept I’m using for this little project is a rather braindead but effective one for my needs: copy the files from the directory that syncs with Google Drive to another directory, thereby having a copy of the files detached from Google Drive so if disaster strikes, we have an isolated copy.
To cover the unlikely scenario of perfect timing whereby the directory is empty when the directory sync happens, I’ll zip up a copy of everything nightly and set that aside, keeping two days worth of archives. (You could of course keep as many as you want but I’m limiting myself to two days since my SD card is only 64GB, and I didn’t want to attach a portable hard drive to the Raspberry Pi for these purposes.)
To provide a bit more detail and put all of this in steps to make it more clear:
  1. Since I’m a Python programmer the backup script will be in Python, and I’ll use dirsync (a Python implementation of a robocopy or rsync-type utility) to sync the Google Drive directory to my backup directory. dirsync only syncs changes so after the initial backup we can safely and efficiently run this hourly.
  2. So I know whether or not the sync worked, I’ll have the script notify me either way. I thought about having it only notify me if there are errors but if someone kicks the cord out of the Raspberry Pi (I’m looking at you, cats) not getting a notification will tell me something went wrong.
  3. Nightly a script will run that zips up the backup Google Drive directory and puts the zip files in an archives directory. This script will also delete files that are more than 48 hours old.

Brief Tangent: Notifications

I thought about using email for notifications since that’s the obvious, easy, lowest-common-denominator solution. But when I do little side projects like this I like to use them as an opportunity to learn something new, so I decided instead to use Pushover and have notifications come to my phone. (I thought briefly about looking into doing a Google Home or Alexa app but that was a bridge too far for this project.)

The long and short of Pushover is it’s a service that lets you send notifications to Android or iOS programmatically. So if you want to try this out just sign up for Pushover (they have a 7-day free trial), verify your email address, and then create an app to get the token you’ll need to use in the script.

Here again I cheated on the “has to be free” requirement and paid the one-time $5 fee for Pushover on my phone, not only to support them but because I may wind up using this on other similar projects.

Back to the Scripts

Refer to GitHub for the full details, but I do want to highlight a couple of things about the scripts.

First, they’re actually totally generic and have nothing directly to do with Google Drive, so the name of the project is probably a bit of a misnomer. overGrive handles the Google Drive sync, and these scripts are really just doing an rsync-style copy from one place to another, and periodically zipping up the results for a bit longer retention. It might be interesting at some future date to make this a truly comprehensive solution and leverage the Google Drive API to do the syncing from Google Drive, but I decided paying $5 for overGrive was a better choice at this particular juncture.

Second, by default the sync script will purge the target directory, meaning files that don’t exist in the source directory will be deleted from the target directory. I went back and forth a bit on that point but decided I wanted an accurate representation of the state of the Google Drive at the point at which the sync occurs, and I didn’t want deleted files cluttering up the backups. Again, people can always get deleted files from the trash on Google Drive unless someone empties the trash or explicitly permanently deletes a file. This is an easy setting to change if you want it to behave differently.


Raspberry Pi + overGrive + Pushover + some Python = success! I now have a handy setup for backing up Google Drive that all told probably took less time to put together than it took to write this blog post about it. I’d be interested to hear if others have solved this problem in different ways.

Fixing Issues with Microsoft LifeCam Studio on Windows 10

A recent Windows 10 update seemed to cause my Microsoft LifeCam Studio to start behaving badly. Actually it wasn’t so much the webcam itself, which seemed to work fine, but when the video on the webcam was active the entire machine would start behaving extremely sluggishly, even though the CPU and RAM stats were both nominal.

To cite a specific symptomatic situation, if while on a Skype call I’d try to interact with another application such as Chrome or Slack, I’d click on the app and after a few second it would get focus. In the case of Slack, as I type the letters wouldn’t appear for several seconds, and then would appear all at once, usually with a few dropped characters. With the video on the webcam disabled, none of this happened.
I dug around a bit and although some of the solutions I found were related to the general webcam issues related to the Windows 10 anniversary update (aka #webcamgate), my webcam wasn’t freezing or refusing to work at all as some people were experiencing, but I figured it was close enough to experiment with some of the solutions that worked for people.
The one that did the trick for me I found as a note here, specifically this series of tweets.
Here’s the step-by-step fix that resolved my issues:
  1. Open regedit (you knew this was coming)
  2. Go to HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows Media FoundationPlatform
  3. Add a new DWORD with the name EnableFrameServerMode and a value of 0
  4. Go to HKEY_LOCAL_MACHINESOFTWAREWOW6432NodeMicrosoftWindows Media FoundationPlatform
  5. Add a new DWORD with the name EnableFrameServerMode and a value of 0
  6. Restart any applications that use your webcam, or reboot
With those registry keys in place my Surface Pro 4 is back to normal.

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 ( in your application.
wfastcgi is maintained by Microsoft as part of Python Tools for Visual Studio (, 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 (, 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 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
  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:
  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:
  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: 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 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:
  6. In the Arguments input box, type the path to the file in the application’s virtual environment:
  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:
    Value: C:appsfoo
  13. Click “Add” again and enter the following:
    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:
  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:
    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 ( 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 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
  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 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 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 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 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:
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 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 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.

    Exporting and Converting iPhone (iOS 9) Wallpaper Files

    I found myself needing to export and convert iPhone (iOS 9) wallpaper files from an old iPhone, and the source photos for these files no longer exist. As with most things Apple this turned out to be a horrendous pain but I was determined not to let Apple win. To paraphrase Ferris Bueller, “If I’m gonna get busted,  it is not gonna be by a company like that.”

    Although getting here was pretty time-consuming, the end result is simple. I did this on Windows but it should work on a Mac as well, provided you can install Pillow and run some Python.

    1. Connect the iPhone to your computer
    2. Backup the iPhone using iTunes
    3. Grab iExplorer and run it, allowing it to connect to the iPhone
    4. In the Backup Explorer, navigate to HomeDomain -> Library -> Springboard
    5. In that directory you’ll see HomeBackground.cpbitmap and LockBackground.cpbitmap files, along with .jpg thumbnails of the files. Export these files from iExplorer to your computer.
    6. The .cpbitmap files are worthless (except to the iPhone) on their own, so finally you need to run a Python script to convert the .cpbitmap files to a usable image file.

    I had to mess with some of the various Python scripts I found online to get it working properly (this one came closest), so if you’re reading this at a future date or using a different version of iOS, I won’t be surprised if it needs further tweaking.

    Hope that helps others retrieve their wallpaper files!

    Fixing DPI Scaling Issues in Skype for Business on Windows 10

    My setup for my day job these days is a Surface Pro 4 and either an LG 34UC87M-B or a Dell P2715Q monitor, depending on where I’m working. This is a fantastic setup, but some applications have trouble dealing with the high pixel density and don’t scale appropriately.

    One case in point is Skype for Business. For some reason it scales correctly as I move between the Surface screen and the external monitor when I use the Dell, but on the LG monitor Skype is either massive on the external monitor, or tiny on the Surface screen.
    After a big of digging around I came across a solution that worked for me, which is to change a setting in Skype’s manifest file (who knew there was one?). On my machine the file is here:
    C:Program FilesMicrosoft OfficeOffice16LYNC.EXE.MANIFEST
    And the setting in question is this:
    Which I changed to this:
    Note that you’ll probably have to edit the file as administrator in order to be able to save it.
    Once I made that change, saved the file, and restarted Skype, it now scales correctly for both the Surface screen and the external LG monitor.

    Installing Python 3 and Django on Dreamhost

    I’m working on a side project for a friend that has zero budget and since I’m already paying for Dreamhost (my favorite and only choice for shared hosting) and totally underusing it, I figured I’d use this project as my opportunity to figure out how to install Python 3 and Django since A) Dreamhost lets you do install things even on their shared platform (one of the reasons I love them!), and B) the default Python on Dreamhost is Python 2.7.3.

    1. Install Python 3.5.1

    This part’s really simple and Dreamhost even documents it nicely on their knowledge base, but for the sake of one-stop shopping I’ll include the steps I performed here. Note that I’m leaving the default Python 2.7.3 in place since I’m not sure what havoc it would wreak to blow it away, so Python 3.5.1 will be installed in such a way that it’ll be run as python3. (For the curious, you can also read more about Python at Dreamhost in general.)

    Before going any further, if you haven’t enabled SSH access for your Dreamhost user you need to do that first since if you can’t log in you can’t install anything.

    1. Log into the Dreamhost web panel
    2. Click on “Users” and then “Manage Users”
    3. Find the relevant user and click the edit button
    4. Under “User Type” choose “Shell user,” and I’d recommend also choosing /bin/bash as the shell type
    5. Scroll to the bottom of the page and click “Save Changes”

    Next, we’ll install Python 3.5.1.

    1. Go to and get the URL for the gzipped source tarball.
    2. SSH into your Dreamhost server
    3. In your user’s home directory, wget the tgz file using the URL you grabbed in step 1:
    4. Extract the Python source:
      tar xvf Python-3.5.1.tgz
    5. cd into the extracted source directory:
      cd Python-3.5.1
    6. Configure Python 3.5.1 with a prefix flag so as not to stomp on anything that’s already installed:
      ./configure –prefix=$HOME/opt/python-3.5.1
    7. Run make and make install:
      make && make install
    8. Add the new Python installation to your path:
      export PATH=$HOME/opt/python-3.5.1/bin:$PATH
    9. Update your bash profile:
      . ~/.bash_profile
    10. Verify that everything’s working (this should output Python 3.5.1):
      python3 -V
    If that all looks good at this point, we’re ready to proceed and create a virtualenv in which we’ll install Django.

    2. Create a virtualenv

    Python 3 ships with pyvenv, but since it works a bit differently than virtualenv which is what I’m used to using, I decided to install virtualenv and use that. Feel free to use pyenv here if that floats your boat.
    1. Use pip3 to install virtualenv:
      pip3 install virtualenv
    2. Create and/or cd into the directory in which you want to put your virtualenv. I tend to put mine in ~/.virtualenvs, so I did this:
      mkdir ~/.virtualenvs
      cd ~/.virtualenvs
    3. Create a virtualenv to use for our Django project (since we installed virtualenv with pip3 the default Python environment will be Python 3.5.1):
      virtualenv my_django_project
    4. Activate your virtualenv:
      source my_django_project/bin/activate
    5. Confirm everything looks correct at this point (this should output /path/to/virtualenv/bin/python3):
      which python3
    If we’re still on track we can proceed to install Django.

    3. Install Django (and your other requirements)

    At this point since we have Python 3.5.1 installed and have successfully created a virtualenv, we can do the usual installation of requirements using pip3, which typically will come from a requirements.txt file. For the sake of illustration we’ll go through installing Django into our virtualenv and making sure it works, but pip3 install -r requirements.txt will be the more typical way of installing all the packages you need.
    1. With your virtualenv activated, install Django:
      pip3 install django
    2. Verify everything is working by starting a Python interpreter:
    3. Import Django to make sure it’s in your virtualenv (this shouldn’t throw any errors):
      >>> import django
    Now that we have verified that our virtualenv is working and sane, we can proceed to the rest of the configuration to get a Django project running successfully in this environment on Dreamhost.

    4. Enable Passenger on Your Web Site

    Rather than the gunicorn or some of the other WSGI servers you may be familiar with, on Dreamhost you can use either Passenger or FastCGI as the application server for Django applications.

    For this post I’ll be using Passenger, a tool with which I was not familiar until I saw information about it on Dreamhost. Passenger is apparently more common in Ruby on Rails setups, but it serves the same purpose and falls in the same place in the stack as any of the other WSGI tools with which you may have experience. You can read more about Dreamhost’s use of Passenger here and here.

    Some Notes About Passenger

    Worthy to note about using Passenger on Dreamhost is that once Passenger is enabled, all requests that come into your domain will be handed off to Passenger by Apache. Passenger will first look see if there are any files matching the request in your domain’s /public directory (and note that the files must be in the /public directory or subdirectories under /public specifically), and if it can’t find an appropriate file, Passenger then tries to handle the request itself.

    To provide a couple of concrete examples, let’s assume you have a file called hello.html in your domain’s /public directory, and a request comes in for Here’s what happens next:

    1. Apache hands the request off to Passenger immediately. This is important to note since Apache is out of the picture entirely other than serving as a proxy to Passenger.
    2. Passenger looks for a file called hello.html in your domain’s /public directory. Since it finds one, it returns that page to the requester.
    Now let’s assume a request comes in for Here’s what happens in that case:
    1. Apache hands the request off to Passenger.
    2. Passenger looks for an appropriate file in /public. This time it doesn’t find one.
    3. Passenger then attempts to handle the request itself, and since later we’ll be configuring Passenger to serve up our Django application using WSGI, at this point Django would be processing the request.

    Enable Passenger

    In order to run a Django application on Dreamhost we’ll need to enable Passenger on the domain on which we’re going to run our Django application.

    1. Log into the Dreamhost web panel
    2. Click “Domains” and then click “Manage Domains”
    3. Locate the domain on which you’ll be hosting your Django application and click “Edit”
    4. Scroll down and under “Web Options” you’ll see a checkbox labeled “Passenger (Ruby/NodeJS/Python apps only).” Check that box.
    5. Scroll to the bottom of the page and click “Change Settings.”
    That’s it for enabling Passenger. Next we’ll throw our Django application at Dreamhost and see what sticks.

    5. Create a Django App

    For the purposes of this post we’ll be creating and configuring a Django application directly on the Dreamhost server. Obviously if you have an application that’s already written that you want to run on Dreamhost you’d be uploading your application’s files as opposed to doing things from scratch on the server, but this should illustrate some of the nuances of what you need to do with your own Django application to get it running on Dreamhost with Passenger.

    1. ssh into the Dreamhost server
    2. Activate the virtualenv you created above:
      source ~/.virtualenvs/my_django_project/bin/activate
    3. cd into the root directory of the web site on which you’ll be running your Django application. Note that this is not the aforementioned /public directory under your web site’s directory, but the root of the web site itself.
    4. Start a new Django project using
      python3 startproject my_django_project
    5. Do a quick gut check by firing up the Django development server:
      cd my_django_project
      python3 runserver
    At this point you should see the Django development server start up without any errors. We’re nearly there! The last step is to configure this newly created Django application to work with Passenger. But before we do that, a quick note about static files.

    Serving Static Files and the Static Root Setting

    It wouldn’t be Django if we didn’t have to stop and say a word about serving static files. Luckily this isn’t anything out of the ordinary, but given how Passenger works you do need to be aware of how to set your STATIC_ROOT to make sure everything comes together smoothly.

    1. Create a static directory under your domain’s public directory, i.e. you’ll wind up with ~/
    2. Go into your Django project’s settings file and add a STATIC_ROOT setting:
      STATIC_ROOT = os.path.dirname(BASE_DIR) + ‘/public/static/’
    With that you should be all set to run collectstatic and have everything work properly. Now let’s move on to configuring Passenger.

    6. Configure Passenger

    In order to have Passenger load up our Django application, we need to create a file in the root of our domain. As with all WSGI files this is what tells the application server, in this case Passenger, how to load up the application so it can handle requests.

    In the root of your domain, create a file with the following contents:

    With that file in place, you should be able to hit and see the default “Congratulations” Django page. Congratulations indeed! You now have a Django application running on Python 3.5.1 on Dreamhost.

    A common error you might run into is something like “no module named foo” or “no module named foo.settings.” If you get something along these lines it means your paths are incorrect, so make sure that your Django project is in a directory directly inside your domain’s root, not in the /public directory. If that isn’t the issue, double-check all the paths in the file.

    Additional Passenger Considerations

    It’s worth noting that if you change your file you need to run pkill python to reload the Django application since Passenger loads your application into memory (which is one of its advertised advantages since it makes things pretty zippy).

    I also saw note of having to run touch tmp/restart.txt but in my experience I didn’t have to do that, so I’m not sure if that’s more of a Rails thing or if I simply didn’t yet run into situations in which that was necessary. I’m noting it here in the event pkill python doesn’t do the trick.

    Final Notes

    There you have it. You now have the latest Python and Django running on Dreamhost. At this point you can load your own Django project, set up a database (note that Dreamhost only supports MySQL, and even though I much prefer Postgres, MySQL works just fine), and do all the usual Django stuff.


    Installing PyGame with Python 3.5 on Windows 10

    Quick installation notes for PyGame with Python 3.5 on Windows 10 since the available installers didn’t work for me, the symptom being the apparently highly frequent “pygame module has no attribute init” error when trying to call pygame.init() after importing pygame.

    First if you’ve run any PyGame installers previously, make sure to clean up anything they installed. The easiest way to do this is to run the installer again and choose the uninstall option, but you may also want to check the Lib/site-packages directory under your Python installation to make sure there aren’t any remnants.

    Next, go here and download the appropriate .whl file for your environment.

    Next, open a command prompt and run:
    pip install wheel

    Finally, browse to the directory where your downloaded .whl file is located and run:
    pip install pygame_file_name_here.whl

    Restart your command prompt to be safe, and at that point you should be able to do this in a Python interpreter without getting errors:
    import pygame

    Hope that saves someone else some head against desk time.