DotCloud and Django
Developing a project in Django using DotCloud
Written by ianonavy
Last Updated: August 18, 2011
Who this tutorial is for:
Developers...
- with a basic understanding of Python syntax.
- who hate dealing with servers.
- who like making things for free (free as in free beer).
Before you read this tutorial
Make sure you have:
- created a(n| free) account at DotCloud. (If you need a tutorial for this, go away.)
- installed the DotCloud CLI (instructions should be given to you after you log in).
- installed Django, which means you should have Python installed. If your computer did not come with Python installed, that probably means you're still using Windows. The best way to install Python is to either buy a Mac or get Linux.
- completed the official tutorial for Django. I'd like you to have at least a basic grasp of what Django is all about before trying to set up a live server on the Interwebs.
What are DotCloud and Django?
By now you should have read through and completed the Django tutorial, so I don't feel the need to explain that Django is a Web framework written for Python. But what on earth is that other thing? DotCloud is a drop-dead simple cloud deployment stack that lets you push your Web projects into the Internet without having to worry about servers and the like. DotCloud manages the server(s) that run your project, so you don't have to worry about things like IP tables or configuring DNS servers. You simply install the command-line interface into your home box and when you're ready to deploy, it's as simple as
dotcloud push myproject. When I say simple, I mean simple once everything is set up properly. Setting up, on the other hand, is not as simple. You'll see what I mean.
1. Setting up the basic files (This is a really long step.)
If you don't already have an existing Django project that you'd like to push to DotCloud, just use the project you created for the tutorial. Before we begin entering any commands into your terminal, make sure your file system looks something like this:
.
|-- dotcloud.yml
|-- mydjangoproject
| |-- __init__.py
| |-- manage.py
| |-- media
| |-- myapplication
| | |-- __init__.py
| | |-- admin.py
| | |-- models.py
| | |-- tests.py
| | |-- urls.py
| | |-- views.py
| |-- settings.py
| |-- static
| | |-- css
| | |-- img
| | `-- js
| |-- templates
|-- postinstall
|-- requirements.txt
`-- wsgi.py
If you see any files that you don't already have, just create blank files and name them as seen above. Once that's done, set up a project using
dotcloud create myprojectname, using whatever project name you like. Of course, your files will vary slightly from the above tree, but it MUST have these basic characteristics:
- In the root directory of your project: a subdirectory containing the Django project and these files: dotcloud.yml, postinstall, requirements.txt, wsgi.py
- The static and media directories in the mydjangoproject subdirectory (of course, it can be named whatever you like).
Let me walk you through the content of each file. You can delete any comments in the code if you like, but I find them helpful when I'm coming back to use them in other projects.
dotcloud.yml
www: type: python db: type: postgresql
This is the main DotCloud configuration file. When you push this project to DotCloud, this file is read to create the correct number of services for your application. I like to use sqlite3 for development and postgresql for production, but that's up to you. YAML is really simple, but if you can't make out what's going on, leave a comment below.
requirements.txt
django PIL==1.1.7
This file is absolutely necessary for DotCloud to know that it has to install Django too. Without it, it has no idea what to do with your code. The
PIL==1.1.7line also installs the Python Imaging Library, which is necessary for your site if you do any sort of image uploading and the like. If you find that a feature of Django requires a module that can be installed using
pip, just include the name in this file.
postinstall
#!/usr/bin/env python
import os
# To import anything under django.*, we must set this variable.
os.environ['DJANGO_SETTINGS_MODULE'] = 'mydjangoproject.settings'
# Import the admin module. The media directory is right under it!
import django.contrib.admin
# Retrieve the absolute path of the admin module.
admindir = os.path.dirname(django.contrib.admin.__file__)
# Add /media behind it.
mediadir = os.path.join(admindir, 'media')
# Compute the path of the symlink under the static directory.
# If the link already exists, delete it.
staticlink = 'static'
if os.path.islink(staticlink):
os.unlink(staticlink)
# Install the correct link.
os.symlink('mydjangoproject/static', staticlink)
staticlink = os.path.join('static', 'admin')
if os.path.islink(staticlink):
os.unlink(staticlink)
os.symlink(mediadir, staticlink)I got this code from another tutorial but fixed it to make it work with my project. You may have to tweak it as well. This little hack is executed after every
push. What it does is create a symlink in DotCloud itself to your actual static files. When you're configuring a sever on your own local computer, you can configure what directory hosts static files (like CSS, JS and images). However, on DotCloud, files are served for you automatically at
/static. So, you can either put your static files outside of the Django project folder and configure your
settings.pyfile to point to it, or you can copy/paste the above hack. Just be sure to replace "mydjangoproject" with the actual name of your folder.
This code also fixes the CSS on the Django admin side.
wsgi.py
import os
import sys
import django.core.handlers.wsgi
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),'mydjangoproject')))
os.environ['DJANGO_SETTINGS_MODULE'] = 'mydjangoproject.settings'
djangoapplication = django.core.handlers.wsgi.WSGIHandler()
def application(environ, start_response):
if 'SCRIPT_NAME' in environ:
del environ['SCRIPT_NAME']
return djangoapplication(environ, start_response)This is the big daddy file that actually works with DotCloud to run your Django server on port 80. Again, make sure to replace "mydjangoproject" with the appropriate directory name. I didn't write this code, so I've no idea how it works. xD
3. Configuring settings.py
Static files
mydjangoproject/settings.py
I'm not going to post the entire settings configuration file, but make sure to add or edit these lines accordingly:
DJANGO_ROOT = os.path.dirname(os.path.realpath(django.__file__))
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
IS_DOTCLOUD = SITE_ROOT.find('dotcloud') != -1Not the prettiest solution, but it gets the job done. Since a lot of the configurations in this file require absolute paths and it's really annoying to have to constantly switch off between
'/home/dotcloud/current/mydjangproject/templates'and
'/home/user/projects/mydjangproject_dotcloud/mydjangoproject/templates, you can just use this:
os.path.join(SITE_ROOT, 'templates')and Python will automatically generate the correct absolute path. This lets you run the Django server locally using
manage.pyAND have it work on DotCloud without messing with the configuration files! You may want to use this technique for the following:
TEMPLATE_DIRS,
STATICFILES_DIRS(
os.path.join(SITE_ROOT, 'static'),), and
MEDIA_ROOT.
Actually,
MEDIA_ROOTrequires an extra little hack to get that working. I discovered when working on a project that if I upload media to a Django server hosted on DotCloud, it is completely erased on the next
push. This is bad. To solve this, I created this solution:
MEDIA_ROOT = os.path.join(SITE_ROOT, 'media') if not IS_DOTCLOUD else '/home/dotcloud/media'. Whenever I upload media to my localhost server, it gets served to a subdirectory media folder in Django, but when I upload on DotCloud, the files are saved in a subdirectory at home, so any
pushdon't override your media files and cause exceptions to be thrown everywhere.
If everything is set up properly, you should be able to access your images at a URL similar to http://[yoururl].dotcloud.com/static/img/image.png after having completed the entire tutorial.
The database
I like to use sqlite3 for development since all of the data is saved in a single file, which is nice when trying to sync with the cloud. All of the data on DotCloud gets wiped once you push, but you're just developing anyway, so it's no biggie.
The following should work for this setup:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(SITE_ROOT, 'development.db'),
'USER': 'root',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}However, once you get into production, you need to start configuring something like postgresql. You'll need a bit of information first, so run this command in your Terminal:
dotcloud info myprojectname.db. The output should be something like this:
cluster: wolverine
config:
postgresql_password: 7h1s15aP0sTgr3SpAs5W0rD
created_at: timestamp
ports:
- name: ssh
url: ssh://postgres@abcd1234.dotcloud.com:1336
- name: sql
url: pgsql://root:cR4zYr0o7pa5Sw0rD@abcd1234.dotcloud.com:1337
state: running
type: postgresqlUsing the information above, your settings.py file should match:
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dotcloud',
'USER': 'root',
'PASSWORD': '7h1s15aP0sTgr3SpAs5W0rD',
'HOST': 'abcd1234.dotcloud.com',
'PORT': '1337',
},Obviously this information will be different for every user, so just make sure that it matches.
Before this database works, you're going to have to actually create the database called 'dotcloud'. Just run
dotcloud run myprojectname.db -- createdb dotcloud. Of course, you could have named this whatever you want, just make sure it matches in
settings.py. The last thing you need to do is run
python manage.py syncdb, and you'll be good to go!
Phew, and we're finally done setting up!
3. Uploading to DotCloud
We're finally ready to push our Django server to the cloud! To do this, simply open up a Terminal and
cdto your root project folder. Type
dotcloud push myprojectnameand hit that sexy enter button of yours, and the magic of DotCloud will put your project on the Web and spit out a fancy URL for you to link to your friends.
4. Scaling
Sometimes we want to add new features to a site that's already in production, but we don't want to erase the existing database. Well, if you set everything up correctly, all of your database information (except user-uploaded media files, i.e. avatars) should be in a separate
dbapplication that won't be harmed when you push to DotCloud. Simply make your changes and run
dotcloud push myprojectnameonce again.
Credits
- http://kencochrane.n...on-to-dotcloud/ for the wsgi.py and postinstall scripts.
- arronhunt for teaching me about requirements.txt
Note: I've actually never used DotCloud to run a production site before. I mainly use it for developing and testing, and then switch to something like Webfaction for final production and deployment. Also, this tutorial probably isn't complete and could use some fine-tuning. Let me know in a reply if you find something unclear or confusing.






Cartoon Clouds
Mountains
Sunrise
Clouds
Green Clouds
None













Help