webdevRefinery Forum: DotCloud and Django - webdevRefinery Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

User is offline ianonavy 

  • Group: Members
  • Posts: 685
  • Joined: 14-April 10
  • Expertise:HTML,CSS,Java,Javascript,Python

Posted 18 August 2011 - 05:54 PM (#1)

DotCloud and Django


Developing a project in Django using DotCloud
DotCloud and Django
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. :P
  • 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.7
line 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.py
file 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. :P

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') != -1

Not 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.py
AND 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_ROOT
requires 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
push
don't override your media files and cause exceptions to be thrown everywhere. :) If your project is still in development, you may find it easiest NOT to use DotCloud altogether until your project is mostly finished.

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: postgresql

Using 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
cd
to your root project folder. Type
dotcloud push myprojectname
and 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. :) You can, of course, use your own domain name, but that stuff costs money, so this tutorial will not focus on it. :P

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
db
application that won't be harmed when you push to DotCloud. Simply make your changes and run
dotcloud push myprojectname
once again.

Credits

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.
reputation += 1 if post.is_helpful else 0
1


Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

2 User(s) are reading this topic
0 members, 2 guests, 0 anonymous users


Enter your sign in name and password


Sign in options
  Or sign in with these services