Author Archives: Dennis Cahillane

JSLint

Check out this interesting clause in the JSLint software license. (From wikipedia)

The JSLint license[2] is a derivative of the MIT License.[3] The sole modification is the addition of “The Software shall be used for Good, not Evil.” This clause has prevented JSLint-related software from being hosted on Google Code[4] and from being included in the Debian free software package repositories.[5]

Interesting that such an innocuous modification to the license could have such dire consequences. I wish the author would drop the clause, since it likely does not decrease “evil” but makes using JSLint more difficult.

Beginners guide to one modern web development stack

This post is for a person who knows how to program, and wants to learn a modern web development stack. At my new job we use Padrino, an alternative to Ruby on Rails, so I’ll be describing that.

First, learn Ruby. I edit my ruby code in Sublime Text 2, it has nice syntax highlighting. I already knew how to program when I learned Ruby, so I simply read this book to pick up the syntax. I then read the first few chapters of this book to learn Ruby community standards, such as not using tabs, and always indenting with two spaces.

Now learn Sinatra and Padrino. Sinatra is a very lightweight ruby-based web framework you can pick up pretty fast. It’s so lightweight that some folks created Padrino to sit on top of Sinatra to recreate some of the features they missed from Rails. Be warned: padrino and sinatra were written by very experienced ruby on rails developers, and their documentation makes constant reference to rails. I don’t know rails so that made the docs a bit difficult at times. Overall though the docs are excellent.

Sinatra Documentation

Padrino Website

Websites consist of HTML, CSS, and javascript. In my stack, these have all been replaced with template languages, respectively, they are haml, less, and coffeescript. Learn all three, they will make you faster. Padrino allows you to mix file types, for example, you can have raw css files mixed in with less files, and it will intelligently handle the situation. There are many template options, haml’s competitors include erb, and less competes with sass/scss.

Haml website

Less website

Coffeescript website

We use the bootstrap javascript library. I’m a mathy guy who loves writing backend code, and find design very hard. Bootstrap is a lifesaver because it lets me make beautiful widgets easily.

Bootstrap demo

JQuery is a totally ubiquitous javascript library. It allows you to make asynchronous websites like gmail.

JQuery homepage

To do professional software development as part of a team, you need to use version control software. I recommend git. It was written by Linus Torvalds (my hero!) in C. He used his advanced knowledge of filesystems to make git much faster than the competition. Git is also how you use the website github, which is central to the open-source world. Go ahead and make yourself a github profile if you don’t have one already.

Git homepage

Github starting guide

There is a lot of talk on hacker sites about SQL and NoSQL data stores. At work we use mongoDB, a NoSQL database system, to store data. The ruby gem to interact with MongoDB is mongoid.

MongoDB homepage

Mongoid homepage

Bundler is a ruby gem that saves a lot of developer time managing libraries (called gems in ruby).

Bundler homepage

Although it is not strictly necessary, I suggest you learn the twitter rubygem, it’s one of my favorites ;)

Twitter gem homepage

Heroku is a way to deploy ruby sites without having to do sysadmin work. They let you put up low traffic sites for free. Once you learn this stack, you’ll be able to put something together in a few days, throw it up on Heroku, and you have a working webpage that would have taken weeks to build and deploy a few years ago. Also, Heroku is a cool company because matz works there, the guy who invented Ruby.

Heroku

If you spend a few weeks learning this stack, build a nice website, and deploy it on Heroku, you’ll be able to get a job in New York or anywhere else hiring Ruby devs. Although many ruby shops use rails, after learning padrino you’ll be able to pick up rails pretty fast.

Javascript

http://open.blogs.nytimes.com/2012/04/04/javascript-meetup-city/

I’m really diving into this blog post. I’m following the twitter account and planning to attend some of these meetup groups in the future. Over the last month of working it has become clear to me that groking javascript is a huge part of being a top 5% web developer. And javascript is only step one, you need to understand it so you can understand something like coffeescript or clojurescript.

My story: from lawyer to ruby hacker

Last winter, Stanford CS Professor Andrew Ng taught an online course in Machine Learning. I took the course, and today the students in the course got an email from Prof. Ng asking for our stories. Here’s what I wrote to him. Maybe this can be an inspiration to someone out there hoping to become a programmer!

tl;dr, in 15 months, I went from unemployed lawyer to employed ruby hacker.

Hello Prof. Ng-

Thanks again for teaching ML. Here is my story.

First some quick background info: the job market for lawyers is very bad. During the economic downturn firms were laying off dozens of people at once, and many froze hiring. I graduated from law school in 2009, and was lucky enough to start working for a big firm. I had no work to do, ever. I would just sit in my office reading the news and wishing for my phone to ring. The firm had way too many young lawyers, and not enough work for us to do. In January 2011, me and few others were laid off. I saw it coming and had been looking for work, but no one was hiring. I was unemployed and my legal career was over before it started.

I decided to teach myself to program and start a new career as a programmer. I came up with this idea from reading Hacker News. There were so many stories about how programmers had such an easy time getting jobs! In contrast, for lawyers there were about five job postings in the entire state of California, and every posting got hundreds of resumes. In fact, when my boss came into my office to fire me, I was installing python onto my work computer ;) I did an “Ask HN” for advice on learning to program, you can check it out here.

http://news.ycombinator.com/item?id=2069477

Only eight days after making this decision, I started volunteering for a non-profit to build them a database system. I put it on my resume like a real job, and worked as hard as I ever had. It took me five months, but I built them that database, and taught myself PHP, SQL, etc at the same time. Nowadays I could build that database in a weekend, in a half-dozen languages ;) .

Then I built a site to apply to Y Combinator. It was a news recommendation website. That’s what got me interested in ML. When I tried to build the recommendation engine, I realized I was in way over my head. About that time the Stanford classes were announced on Hacker News. I couldn’t believe my luck! So I devoted myself full time to the AI, ML, and database classes. I also downloaded Stanford CS106A and B, and worked through those.

In these classes, the rate of learning for me was faster than working through books by myself. You can teach yourself syntax, but it is difficult to improve your overall skills without someone guiding you and giving you exercises that are appropriate for your ability. The classes gave me a way to measure my progress. Was I a “real” programmer or just a pretender? Since I could do the work, I was a real programmer! And when I got stuck on an exercise, I could go to the forums for a hint. The forums were key to the course.

Three weeks ago, I got a paid internship as a ruby hacker. I mentioned the Stanford classes during the interview and my interviewer had heard of them. I am no longer adrift without a career, in contrast to thousands of underemployed lawyers nationwide, banging their head against the wall, hoping for a miracle. At my internship, I have already committed code that is in production (despite never having written any ruby when I was hired). In the past 15 months I have learned enough that I was able to pick up ruby/padrino and start contributing quickly. After this internship I am confident I will be able to get a job hacking ruby, maybe at the same place, maybe somewhere else.

Programming, especially mathy programming like ML, gives me great pleasure and is a wonderful way to spend time. I’m really surprised that I can get paid for doing something that is so fun!

I am currently taking the Algorithms class. I plan to work through as much of the Stanford CS curriculum as possible, and give myself a virtual “Stanford CS degree” on nights and weekends while hacking ruby during working hours. In a year or two I will be in really good shape, having real-life working experience, and having learned so much from online courses. Thanks to Hacker News and these online courses, I have a new career and am having the time of my life!

Thank you so much!

Get wifi working on a Dell Vostro 3450 on Linux Mint 12

I bought myself a nice new Dell laptop, a Vostro 3450. Naturally the first thing I did was overwrite the default Windows 7 install with Linux, in this case Linux Mint 12. The wifi didn’t work out of the box, due to a problem with the iwlagn kernel driver. When I tried to configure it using the graphical tool, the little switch refused to go from “off” to “on”.

The wireless chipset is “Intel Corporation Centrino Wireless-N 1030.” My install of Linux Mint 12 came with the 3.0.0-12 kernel. (Find out your kernel version by typing uname -a at the Terminal command line.) I fixed the problem by upgrading my kernel to 3.0.0-16. To do so, I typed the follow at the command line:


~ $ sudo apt-get install linux-headers-3.0.0-16 linux-headers-3.0.0-16-generic linux-image-3.0.0-16-generic --fix-missing

Then I rebooted the laptop, grub automatically chose the new kernel, and wifi started working!

My response to Senator GIllibrand

Yesterday I emailed my Senator urging her to oppose the “have corporations censor the Internet” SOPA bill. Here is her response, followed by my response to her.

Dear Dennis,
Thank you for writing to me regarding S. 968, the PROTECT IP Act of 2011. I understand your concerns.

I am a cosponsor of this legislation because I believe that we must protect American intellectual property against foreign websites that infringe upon our rights. By empowering the Attorney General of the United States to go after foreign infringing websites, this legislation becomes a necessary tool to ensure that U.S. companies remain competitive in the world marketplace. I recognize that there are technical concerns with the enforcement of this bill that need to be addressed. I am committed to working with my colleagues in the United States Senate to ensure that this legislation protects the Constitutional rights of Americans and does not stifle lawful free speech or innovation on the internet.

Thank you again for writing to express your concerns, and I hope that you keep in touch with my office regarding future legislation. For more information on this and other important issues, please visit my website at http://gillibrand.senate.gov and sign up for my e-newsletter.

Sincerely,

Kirsten E. Gillibrand
United States Senator

My response:

This is very dissapointing news. Please reconsider your stance and oppose this terrible bill.

The Internet become great without corporate censorship and this bill will have devastating consequences. Giant unaccountable media companies control enough of our lives, there is no need to give them censorship power over the Internet. And I resent the implication in your email that “foreign websites” are somehow suspicious or bad. This legislation will allow governments and corporations to remove websites from the internet without a hearing, an extraordinary and unecessary legal remedy. It is inevitable that this power will be abused.

Please realize that while we currently have an upstanding citizen as Attorney General, that is not always the case. I’m sure you remember Alberto Gonzalez and the other Bush Administration AG’s who enthusiastically supported torture, extraordinary rendition and other awful things. In our lifetime we will likely have to endure more Republican administrations with a similar lack of scruples for human rights. Empowering the executive branch to censor the Internet without hearings will move the US government closer to countries like Russia and China, which is clearly the wrong direction.

If your idea of protecting free speech is trusting multinational corporations, then I have beachfront property to sell you in Arizona.

A concerned citizen,
Dennis Cahillane

How to get sound working well in Ubuntu on a MacBook

Linux has come a long way since I installed Red Hat 5.2 on a Pentium 90Mhz machine. Ubuntu “just works” on a MacBook from 2009, except the sound is too quiet. There is a sound setting you have to change through the command line:

amixer sset 'Front Speaker' 100%

While you’re at it, you can get rid of that funny red light shining out of the headphone jack with this command:

amixer set IEC958 off

Found that one here.

Using pinboard on an iPad

Pinboard is a bookmarking site to replace delicious. To add a site to your pinboard bookmarks, Pinboard provides javascript bookmarklets. Unfortunately, there is no easy way to add javascript bookmarklets to your iPad Safari bookmarks. Pinboard provides an email address for mobile device users, but there is a better way.

Visit this blog post on your iPad. I needed to click on “Standard Site” at the bottom of the page to be able to copy anything. Then when you tap the source code, there will be a “view source” icon where you can visit another page that has the plain text of the javascript where you can highlight it and Copy it.

Copy this javascript into your clipboard by highlighting it and taping “Copy”. (The javascript is taken verbatim from the pinboard site).

javascript:q=location.href;p=document.title;void(t=open('https://pinboard.in/add?later=yes&noui=yes&jump=close&url='+encodeURIComponent(q)+'&title='+encodeURIComponent(p),'Pinboard','toolbar=no,width=100,height=100'));t.blur();

Now tap the rightmost button on the address bar, and then tap “Add Bookmark”. Erase the text in the top box and type “Pinboard”. At this point, you will not be able to edit what is being bookmarked on the second line. And change the third line to “Bookmarks Bar”.

Now tap the Bookmarks button (the fourth button on the Safari toolbar). Tap “Edit” and select your pinboard bookmark. You will be allowed to edit the text on the second line. Delete what is there, and paste the javascript from your clipboard. Navigate back to your browser, visit a page, and tap your pinboard bookmarklet on the Bookmarks Bar. You have added the page to your pinboard bookmarks.

Note that these instructions work in general for bookmarklets. Just get the text into your iPad clipboard somehow, then paste the javascript into an existing bookmark with the “Edit” bookmarks trick.

Rating with stars (jQuery, CSS, Django)

Here is some code I wrote to have an arbitrary number of stars (such as five) rate items. The jQuery code responds to mouseover events and mouse click events by changing the look of the stars and passing the rating to the server by visiting a URL. To see them in action, visit www.momsrobot.com/beta and rate some links!

Here is the jQuery. It uses some Django template stuff. It was written under jQuery 1.4 but is pretty simple, so should work under different versions.

    <script type="text/javascript" src="/static/jquery-1.4.js"></script>
    <script type="text/javascript">
      $(function() {
        $('.star').click(function(){
          $(this).addClass('on rating');
          $(this).prevAll().addClass('on rating');
          $(this).nextAll().removeClass('on rating');  
          //	How to select the parent div of 'this'?
          $(this).parent().addClass('rated');
          var hit_id = $(this).parent().attr('id');
          var rating = $(this).siblings().add(this).filter('.rating').length
          $.post("/rate/", {user: "dennis", rating: rating, id: hit_id}, 
            function(data) {
              // alert(data);
            });
        });
      });

      $(function() {
        $('.star').hover(
          function(){
            $(this).addClass('on');
            $(this).prevAll().addClass('on');
            $(this).nextAll().removeClass('on');
          },
          function(){
            $(this).siblings().add(this).removeClass('on');
            $(this).siblings().add(this).filter('.rating').addClass('on');
          }
        );
      });
    </script>
<script type="text/javascript">

As you can see, the jQuery code works by manipulating the DOM. It works in conjunction with the following Django template code and CSS. The Django template stuff could easily be adapted to other frameworks. To change the number of stars, change the number of div’s. To change the initial rating, change the “on rating” class members.

<div class="rating" id="{{item.pk}}">
  <div class="star on rating"></div>
  <div class="star on rating"></div>	
  <div class="star on rating"></div>	
  <div class="star"></div>	
  <div class="star"></div>
<div class="userrating" id="{{item.pk}}"></div> 
</div>

And here is the CSS. You’ll need to provide your own star .png images! I found mine in the public domain.

.star {
     width:29px;
     height: 29px;
     background-image:url(white_star.png);
     float:left;
}

.on {
     background-image:url(yellow_star2.png);
}

.rated &gt; .rating {
     background-image:url(red_star.png);
}

With the code so far working together, you’ll have some stars that light up and change colors. This code talks to your serverside code through this line:

$.post("/rate/", {user: "{{ username }}", rating: rating, id: hit_id}

The username, rating, and id (of whatever is being rated) is posted to the URL /rate. You set up your serverside code to process whatever is posted to /rate. Like so:

def rate(request):
    if request.is_ajax():
        if request.method == 'GET':
            message = "fail"
        elif request.method == 'POST':
            user = request.POST.get('user')
            rating = request.POST.get('rating')
            this_id = request.POST.get('id')
            message = str(user) + " "+ str(rating) + " " +str(id)
    else:
        message = "No XHR"
    # do something
    return HttpResponse(message)

Of course you’d need to set your urls.py to pass /rate POST data to this function. I hope this code helps you.

Running Django 1.3 on CentOS 5.5

This post teaches you how to set up a CentOS 5.5 virtual server in the cloud, and install Django 1.3.  There is a lot of information about this scattered around the Internet, but I haven’t seen one post putting it all together. Unfortunately it’s more complicated than just “yum install python django” because CentOS 5.5 relies on python 2.4 for some system-level stuff, and Django 1.3 needs a more modern python than 2.4. So I use virtualenv to have python 2.7 installed and running alongside the CentOS python 2.4. If you already have CentOS up and running simply skip the part about setting up a server for the first time.

First, set up a virtual server in the cloud. I recommend Rackspace.

Use the Rackspace web interface to create a Linux server instance. This post uses CentOS 5.5. CentOS is Red Hat without the monthly fees.

Use the Rackspace web interface to discover your public IP address, and ssh in using your root account. I know this feels really dirty and wrong, but we’ll fix that right away. Get the root password from the email rackspace sends you when you reset the password. Alternatively, use the rackspace web console to do this root account dirtiness.

Pick a username for yourself, like hampsterhuey. As root create your account (lines beginning with # are to be typed at the shell)

# useradd hampsterhuey
# passwd hampsterhuey

(type your password, like gooeykablooie)

Now change the root password
# passwd

Still as root, add yourself to the wheel group
# vi /etc/group

find the line in /etc/group that looks like
wheel::10:root

change to:
wheel::10:root,hampsterhuey

Save the file. Now give yourself sudo power by running
# /usr/sbin/visudo

find the lines
## Allows people in group wheel to run all commands
# %wheel  ALL=(ALL)       ALL

Add to end to not type password on sudo
hampsterhuey ALL=(ALL) NOPASSWD: ALL

uncomment the %wheel line.

save the sudoers file. Now that hampsterhuey is at full power, we can stop stomping around as root.
# vi /etc/ssh/sshd_config

Find this section in the file, containing the line with “PermitRootLogin” in it. Edit it to say “no” like this

#LoginGraceTime 2m
#PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6

* Now you’ll need to restart the sshd service:
# sudo /etc/init.d/sshd restart

Log out of your instance and try to ssh in as root. It won’t work. Ssh in as yourself to continue.

Add /sbin and /usr/sbin to your path in the file .bash_profile in your home directory to avoid driving yourself insane.

install apache and mysql
# sudo yum -y httpd
# sudo yum -y mysql

If you start apache at this point
# sudo /etc/init.d/httpd start
it won’t allow connections! You need to put a hole in your firewall. The default iptables config doesn’t allow incoming TCP on port 80.

This page can explain IPTables to you, or just follow my instructions.
http://wiki.centos.org/HowTos/Network/IPTables

Edit /etc/sysconfig/iptables. Open up 80 and 443 to allow http and https with these lines in your config:

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT

They fit in like this:

# Firewall configuration written by system-config-securitylevel
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT

-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT

ha! ha! Manual configuration not recommended! Good one!

now restart iptables and apache
# sudo /etc/init.d/iptables restart
# sudo /etc/init.d/httpd restart

and visit your public IP in your web browser of choice to verify it works. You should see a simple page saying “It works!”

Now we compile python 2.7.2. Unfortunately you can’t use the CentOS package system to install this version of python, or any recent version. CentOS 5.5 ships with Python 2.4.3, and it relies on that version of python for various system-level tasks.

Make yourself a directory for source code
# cd
# mkdir src
# cd src

Download the python package
# wget http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tar.bz2
# tar jxvf Python-2.7.2.tar.bz2
# cd Python-2.7.2

Now compile python. I’ve added some options to the configure script to install python into /opt. I like to install custom packages into /opt to keep track of them. Running make altinstall instead of make install creates binaries with the version number attached, like python2.7 instead of python. We have to do that to avoid colliding with the python binaries on the system that are version 2.4.
# ./configure --enable-shared --prefix=/opt --exec-prefix=/opt
# make
# sudo make altinstall

Now we compile mod_wsgi 3.3. This is how Apache talks to Django.

# cd
# cd src
# wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
# tar zxvf mod_wsgi-3.3.tar.gz
# cd mod_wsgi-3.3
# declare -x LD_LIBRARY_PATH="/opt/lib"
# ./configure --with-python=/opt/bin/python2.7
# make
# sudo make install

Now if you tried to restart apache you’d have shared library problems. Let’s fix that.

# sudo cp /opt/lib/libpython2.7.so.1.0 /usr/lib64
# sudo ln -s /usr/lib64/libpython2.7.so.1.0 /usr/lib64/libpython2.7.so

Now edit /etc/httpd/conf/httpd.conf

at the top of Section 1 add
WSGIPythonHome /opt/virt-env

among the other mod_’s add
LoadModule wsgi_module modules/mod_wsgi.so

restart Apache
sudo /etc/init.d/httpd restart

Now you’re running apache with mod_wsgi compiled against python 2.7.2 like a boss.

Now install virtualenv, here is a page explaining what it is.
http://pypi.python.org/pypi/virtualenv

Same as before, change directory to ~/src
# cd ~/src
# wget http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.6.4.tar.gz#md5=1072b66d53c24e019a8f1304ac9d9fc5

etc…

Now we install the mysqldb python library under a virtual environment using virtualenv.

# cd /opt
# sudo mkdir /virt-env
# sudo virtualenv --no-site-packages --python=/opt/bin/python2.7 virt-env/
# source /opt/virt-env/bin/activate
# sudo pip install --upgrade MySQL-python

Now after all that, we install Django. Python has several package managers. This tutorial uses pip. For this to work, you must still be in the “virtual environment” created when you ran the command # source /opt/virt-env/bin/activate.

#sudo pip install Django

To get Django working, edit httpd.conf. Find the line:
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

and add this line right after it

WSGIScriptAlias / /opt/momsrobotco/apache/django.wsgi

Add the following to the Alias section:

Alias /robots.txt /usr/local/wsgi/static/robots.txt
Alias /favicon.ico /usr/local/wsgi/static/favicon.ico

AliasMatch ^/([^/]*\.css) /usr/local/wsgi/static/styles/$1

Alias /media/ /usr/local/wsgi/media/
Alias /static/ /usr/local/wsgi/static/

<Directory /usr/local/wsgi/static>
Order deny,allow
Allow from all
</Directory>

<Directory /usr/local/wsgi/media>
Order deny,allow
Allow from all
</Directory>

WSGIScriptAlias / /usr/local/wsgi/scripts/django.wsgi

<Directory /usr/local/wsgi/scripts>
Order allow,deny
Allow from all
</Directory>

Now edit /usr/local/wsgi/scripts/django.wsgi to look like this. Replace your “path =” line with the location of your Django project.

import os
import sys
path = '/opt/django/momsrobotco'
if path not in sys.path:
sys.path.append(path)

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Now install MySQL using regular CentOS tools.
# yum -y install mysql-server
#mysql -u root -p

(no password, just hit enter)
Now use SQL language to create your Django database for your project, and add the username and password to your settings.py. Here is what this should look like.

CREATE DATABASE momsrobotco;
CREATE USER 'momsrobotco'@'localhost' IDENTIFIED BY "cool password";
GRANT ALL PRIVILEGES ON momsrobotco.* TO 'momsrobotco'@'localhost' WITH GRANT OPTION;

Now upload your django project to the server, Make sure to put it in the same directory as the “path =” line in django.wsgi. When running django behind apache, be aware that there is a lot of caching going on (unlike when using the development server on your local machine). This mean you’ll have to restart Apache when you make changes, and sometimes even then your changes will not show up for a while. Long story short, don’t try to develop a site on a machine running django behind Apache.

When you’re doing django stuff, make sure to run the line
# source /opt/virt-env/bin/activate
First. Then when you type “python” it will load python 2.7 instead of python 2.4. So if you want to muck around at the shell, get into your project directory and type:
python manage.py shell

I hope this tutorial was useful for you! I’ll try to help anyone who posts a comment. Also check out #django on IRC, those guys helped me out big time.

Follow

Get every new post delivered to your Inbox.