Thursday, January 14, 2010

Accessing Inherited Models from the Parent in Django

One of the neat features of Django's ORM is Model inheritance (table-level). It allows several neat data design patterns to occur. Here's an example. Let's say we're developing a website for a game company. The company sells two types of products: board games and video games. All of the products will share some data in common, name and product_id for example, but we also need to store specific details about each. Using model inheritance we can do something as follows.

class Product(models.Model):
name = models.CharField(max_length=75)
product_id = models.SmallIntegerField()
price = models.DecimalField()

class BoardGame(Product):
num_of_players = models.SmallIntegerField()
game_type = models.CharField(max_length=50)

class VideoGame(Product):
PLATFORM_CHOICES = (
('wii', 'Wii),
('xb3', 'Xbox 360'),
('ps3', 'Playstation 3'),
)
platform = models.CharField(max_length=3, choices=PLATFORM_CHOICES)
In a real use-case scenario you'd most likely have more than 1 field per, but for this example I wanted to keep things simple.

The way Django implements this, if you were to query one of the child models, you'd be able to access the methods from the parent models...
b = BoardGame.objects.all()[1]
print b.name

>>> 'Djangopoly'
Another thing that's cool is child instances have a parent instance record. Using the "Djangopoloy" game from above, which is technically type BoardGame, one could still query Product and retrieve it.
p = Product.objects.get(name='Djangopoly')
This is really useful, but sometimes you need to go the opposite direction, and this is where Django's implementation stops. The link can't go from a Product model instance to a BoardGame. It can't retrieve state as if it was of type BoardGame.
print p.platform

>>> CAN'T DO THAT!
Because the need for this seems to be arising more often than not lately for me, I put together a re-usbale bit of code to overcome this limitation. I'll post the code below (a GitHub gist), but using it is actually quite simple.

It works by providing an abstract model that the parent model inherits from instead of models.Model:
from inheritance.models import ChildAwareModel

class Product(ChildAwareModel):
...

pass
Then, an inner class "Inheritance" is supplied to describe children of the model.
class Product(ChildAwareModel):
...

class Inheritance:
children = (
'myapp.models.BoardGame',
'myapp.mdoels.VideoGame',
)
Only children that need to be reversed to should be set. Once that is configured, a method "get_child_model()" will become available, and can be used like so:
p = Product.objects.get(name='Djangopoly')
b = p.get_child_model()
print b.num_of_players

>>> 4
I'm finding this particularly useful when I've created an aggregate type page -- that is a page that shows a summary of all the generic types (Product) -- but need to on user-click show them some type of product-specific detail.

The implementation for ChildAwareModel is below. Save it somewhere on your python path and enjoy. :)


ChildAwareModel Gist

Tuesday, January 12, 2010

Version Control Commit Messages

Soooooo... I think I'm going to put in a proposal at work. All commit messages for our Mercurial DVCS need to be in 16-year-old girl language....

  • "Like, the JSON api is totally updated"
  • "fixed the buggies kk thx bai <3"
  • "this import module is sooooo cuties!!!!!11`1"

Sunday, January 10, 2010

Meh @reading (but Yay to reading on the iPod)

I can't be the only programmer who finds reading a chore? And what about those 5-billion page programming tomes? Am I the only one who never finishes those?


It happens to be that I just found something about reading that totally rocks: Reading on the iPhone/iPod Touch is totally different (better different). HA! I bet you didn't know I was going to say that (well if you read the title of this post you probably did.. that was totally a spoiler).

Now it seems that I am finding I actually enjoy reading again (did I just write that?). I ended up landing a very fetching iPod touch for Christmas which has been having it's battery drained near non-stop since the package was opened. As a curiosity of sorts, I threw a lot of the big name apps onto it, including Kindle for Ipod, and purchased a book I had been eying for a while, Javascript: The Good Parts (Douglas Crockford), to try out the experience of reading on the iPod.

It seems so wrong but I found I actually prefer reading on the iPod. I've read a number of paper books, and I've tried reading eBook/PDFs on the computer, but neither of them really jump out at me. But the iPod... the iPod I like.

The reason for this, I suspect, is that reading on the iPod is not intimidating. The screen only shows 2 paragraphs at a time. I don't need to be worried about the rest of the book, I'm only looking at these 2 paragraphs. What I think this does for me is it allows me to read the book without feeling like I have to rush to get to the end.

My wife thinks it's silly, but whatever -- I'm already on my 2nd book.... Real World Haskell (Donald Stewart). Oooooh yes, it's Haskell time! Expect some really weirded out blog posts from me in the future about functional programming.

  © Blogger template 'Minimalist G' by Ourblogtemplates.com 2008

Back to TOP