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.
- Log into the Dreamhost web panel
- Click on “Users” and then “Manage Users”
- Find the relevant user and click the edit button
- Under “User Type” choose “Shell user,” and I’d recommend also choosing /bin/bash as the shell type
- Scroll to the bottom of the page and click “Save Changes”
Next, we’ll install Python 3.5.1.
- Go to https://www.python.org/downloads/release/python-351/ and get the URL for the gzipped source tarball.
- SSH into your Dreamhost server
- In your user’s home directory, wget the tgz file using the URL you grabbed in step 1:
wget https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz - Extract the Python source:
tar xvf Python-3.5.1.tgz - cd into the extracted source directory:
cd Python-3.5.1 - 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 - Run make and make install:
make && make install - Add the new Python installation to your path:
export PATH=$HOME/opt/python-3.5.1/bin:$PATH - Update your bash profile:
. ~/.bash_profile - Verify that everything’s working (this should output Python 3.5.1):
python3 -V
2. Create a virtualenv
- Use pip3 to install virtualenv:
pip3 install virtualenv - 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 - 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 - Activate your virtualenv:
source my_django_project/bin/activate - Confirm everything looks correct at this point (this should output /path/to/virtualenv/bin/python3):
which python3
3. Install Django (and your other requirements)
- With your virtualenv activated, install Django:
pip3 install django - Verify everything is working by starting a Python interpreter:
python3 - Import Django to make sure it’s in your virtualenv (this shouldn’t throw any errors):
>>> import django
4. Enable Passenger on Your Web Site
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 http://yourdomain.com/hello.html. Here’s what happens next:
- 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.
- 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.
- Apache hands the request off to Passenger.
- Passenger looks for an appropriate file in /public. This time it doesn’t find one.
- 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.
- Log into the Dreamhost web panel
- Click “Domains” and then click “Manage Domains”
- Locate the domain on which you’ll be hosting your Django application and click “Edit”
- Scroll down and under “Web Options” you’ll see a checkbox labeled “Passenger (Ruby/NodeJS/Python apps only).” Check that box.
- Scroll to the bottom of the page and click “Change Settings.”
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.
- ssh into the Dreamhost server
- Activate the virtualenv you created above:
source ~/.virtualenvs/my_django_project/bin/activate - 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.
- Start a new Django project using django-admin.py:
python3 django-admin.py startproject my_django_project - Do a quick gut check by firing up the Django development server:
cd my_django_project
python3 manage.py runserver
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.
- Create a static directory under your domain’s public directory, i.e. you’ll wind up with ~/yourdomain.com/public/static
- Go into your Django project’s settings file and add a STATIC_ROOT setting:
STATIC_ROOT = os.path.dirname(BASE_DIR) + ‘/public/static/’
6. Configure Passenger
In the root of your domain, create a passenger_wsgi.py file with the following contents:
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 passenger_wsgi.py file.
Additional Passenger Considerations
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
Enjoy!
Quick follow-up about STATIC_ROOT and MEDIA_ROOT settings.
I have my Django project set up with a settings module as opposed to a single file, so these settings worked for me to put files in the right place when running collectstatic, or uploading files in the app using FileField or ImageField:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), '../', 'public/static/')
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), '../', 'public/media/')
MEDIA_URL = '/media/'
thank you for the article. i just went through the process of standing things up and used your guide for my passenger woes and it helped quite a bit. Cheers!
Excellent! Glad it was helpful.
For the STATIC_ROOT and the MEDIA_ROOT do you mean that we replace the '../' with your domain name as indicated below?
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'your_domain_name.com/', 'public/static/')
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'your_domain_name.com/', 'public/media/')
MEDIA_URL = '/media/'
or could it just be like this?:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'your_domain_name.com/public/static/')
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'your_domain_name.com/public/media/')
MEDIA_URL = '/media/'
After hours putzing around on other sites (including Dreamhost's), this is what finally made things work. Fantastic, thanks a bunch!
Always great to hear when people found this helpful. Thanks!
Matt – I realize that this post is old, but so far I found it incredibly helpful. I am up to the stage where you show how to create a django app. I am, however, using a flask app. Are there any material changes to the instructions from that point onward if using flask rather than django?
Hi Richard — there shouldn't be any major differences for Flask since the underpinnings would be more or less the same. I'd love to hear how it works out.
Really very informative and creative contents. This concept is a good way to enhance the knowledge.thanks for sharing. please keep it up
Really very informative and creative contents. This concept is a good way to enhance the knowledge.thanks for sharing. please keep it up
python training in chennai
hadoop training in chennai