meetteem: tech addict

software development, etc.

Viewing posts tagged 'django'

Django 1.0 Released!

It's finally here!

~$ python -c 'print __import__("django").VERSION'
(1, 0, 'final')

Using ActiveRecord Migrations in Django Apps?

In Episode 40 of the Rails Envy podcast, using Rails ActiveRecord migrations in Django apps was mentioned.

I'm comfortable with AR, and AR migrations are more readable and convenient than using plain SQL to migrate the models, so I decided to give it a try. (I use plain SQL when I migrate the database schemas in my Django projects and I haven't used Django Evolution yet.)

Here's what I did. (If you wanna see the AR migration script now, click here.)

Test Bed

I created a Django project, set up my database, and updated settings.py.

$ django-admin.py startproject mysite
$ cd mysite
$ mysqladmin create mysite
$ mate .                   # open the project in TextMate and update the db connection info in setting.py

Next, I created a Django app called blog. Yeeeehaw! Blog!

$ ./manage.py startapp blog

And added the Post model in blog/models.py

# blog/models.py
from django.db import models

# Create your models here.
class Post(models.Model):

    title = models.CharField(max_length=60)
    body = models.TextField()

    date_created = models.DateTimeField()
    date_published = models.DateTimeField()

Then I added the blog application in the INSTALLED_APPS tuple in settings.py, validate, and created the blog tables.

$ ./manage.py validate
$ ./manage.py syncdb

Check out the CREATE TABLE statements for the blog app.

$ ./manage.py sql blog
BEGIN;
CREATE TABLE `blog_post` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `title` varchar(60) NOT NULL,
    `body` longtext NOT NULL,
    `date_created` datetime NOT NULL,
    `date_published` datetime NOT NULL
)
;
COMMIT;

A New Attribute

Uh. Okay. Now, for the fun part. I added date_updated to the Post model. Kept it simple.

class Post(models.Model):
    .
    .
    .

    date_updated = models.DateTimeField()

And checked the newer CREATE TABLE statements for the blog app.

$ ./manage.py sqlall blog
BEGIN;
CREATE TABLE `blog_post` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `title` varchar(60) NOT NULL,
    `body` longtext NOT NULL,
    `date_created` datetime NOT NULL,
    `date_published` datetime NOT NULL,
    `date_updated` datetime NOT NULL
)
;
COMMIT;

Hmm.. A new NOT NULL column date_updated.

The ActiveRecord Migration Script

Now for the standalone ActiveRecord migration script.

# File: add_date_updated.rb
require 'rubygems'
gem 'activerecord'
require 'activerecord'

# Setup database connection
ActiveRecord::Base.establish_connection(
  :adapter => "mysql",
  :database => "mysite",
  :username => "teem",
  :password => "passw0rd",
  :host => "localhost"
)

# Migration script
class AddDateUpdated < ActiveRecord::Migration
  def self.up
    add_column :blog_post, :date_updated, :datetime, :null => false
  end

  def self.down
    remove_column :blog_post, :date_updated
  end
end

# Migrate
AddDateUpdated.migrate(:up)

The script is pretty straight-forward. It sets up the database connection, defines the migration script, and finally runs the migration. You can always migrate down by replacing the :up with down, but that's a little obvious, right? Also, note that the table name is blog_post, and also the :null => false condition.

Notes, Etc.

  1. It's not really DRY, since the db connection information is in the script itself. Maybe creating a database.yml and putting db connection info there could make things DRYer. The Ruby script and the settings.py can simply load the yaml instead.
  2. I didn't bother with the schema information, versioning stuff. Should I?
  3. If you wanna try it out, the ActiveRecord documentation is here and the ActiveRecord Migration documentation here.

My Reading List

I added a small Django app to sort of track my progress in reading books. I hope this will motivate me to read the books I bought over the past year and a half. Last time I checked, I haven't even touched about 25 of my books.

So little time, so much to do.

Now, to actually add the books to the list...

Another Django Update, 1.0 Draws Near

Django 1.0 alpha was released yesterday. I'm running this blog on trunk so I updated this blog to use the bleeding edge feature recently merged to the trunk: the newforms-admin. The last time I updated was when the queryset-refactor branch was merged to the trunk. With Brian Rosner's walkthrough and screencast, the migration wasn't a pain. It took me about 10 minutes to migrate, switching back and forth the NFA wiki and the blog code.

Thank you, Django people. You've made the world a better place.

Tagging

I've added tagging to this site. As most of my avid readers know, this blog is made in Django.

A little background how I did it and why I choose to do it that way.

I had two options on how to implement tagging: generic relations using the contenttypes framework and many-to-many relations.

I went with the many-to-many relationship primarily because I had the impression that Contenttypes API isn't stable atm:

Generic relations will most likely be moved out of core and into the content-types contrib package to avoid core dependencies on optional components.

Well, as far as I can see, the django trunk has already made this change.

The second reason I went with the ManyToMany relationship was because I didn't need or want the Generic relations. I just needed to tag posts.

So there.

<< Older Posts