Living on the Edge

This Week in Django 5 - 2008-01-06

Posted on January 07, 2008

This Week in Django is a weekly podcast about all things Django.

This week Brian Rosner joins me once again. We discuss the Akita interview of Adrian Holovaty, a few changesets, the Queryset Refactor branch, a Tip of the Week, and a few questions from the IRC Channel.

Please see the Show Notes below for all the pertinent information and links

Downloads

AAC Enhanced Podcast (28.2 MB, 58:31, AAC)

MP3 Edition (26.8 MB, 58:31, MP3)

The Enhanced Podcast version contains screenshots and easy access links to all of the items I discuss throughout the podcast.

Feeds Available

This Week in Django – AAC Edition

This Week in Django – MP3 Edition

Show Notes

Big News (1:08)

Tracking Trunk (8:12)

  • Changeset (6998) – added a last filter, which returns the last item in a list.
  • Changeset (7001) – Session bug in odd cases where sessions kept being created in the database
  • Changeset (6996) – Reverted ‘regroup’ template tag changes from Changeset 6956 because it didn’t work when using a filter that had a parameter with spaces in it.

Branching & Merging (17:59)

Community Catchup (33:28)

Tip of the Week (42:33)

This week’s Tip of the Week comes from Brian Rosner and involves using custom Managers to simplify your filters and keep things DRY.

Each model has a Manager instance associated with it. It is typically accessed through MyModel.objects. Django lets you change this to allow you to have customized methods in objects or even add more Manager instances to your model.

Let’s take a look at a good use case for using your own manager. Here is a very familiar models.py you might have created:


from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    active = models.BooleanField(default=False)

Now lets say I need to get all the active products a lot in my code. Well to accomplish this now I would execute the following code:


Product.objects.filter(active=True)

This will give me all the products that are currently active. Well lets simplify this by using a custom manager. Lets add some code to our model:


from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    active = models.BooleanField(default=False)

    objects = models.Manager()
    active_objects = ActiveProductManager()

We have now added objects and active_objects. It is critical that you explicitly assign objects since it will cause some confusion to Django. However, this is nice to see that you can just as easily change out the object that sits behind the objects property of the class. Now lets see the code in the ActiveProductManager@ class:


class ActiveProductManager(models.Manager):

    def get_query_set(self):
        queryset = super(ActiveProductManager, self).get_query_set()
        return queryset.filter(active=True)

Make sure ActiveProductManager is defined before calling it in the Product model. If you have a lot of manager classes in the models.py it might be a good idea to place them in a managers.py file and import them at the top of models.py.

Ok, so in the ActiveProductManager class above we are overriding the get_query_set method to provide our own query set to use by default by the manager. To get a better idea of how the Manager class works check out the source code. It is very straight-forward. Now we have enabled ourselves to execute this line of code to get active products:


Product.active_objects.all()

You can also perform any other queryset filtering, exluding, etc.. since it is just a regular queryset being passed back.

IRC Ad Naseum (49:22)

How can I get the current date/time to be automatically added when I save a new record or update a record?


import datetime
created_at = models.DateTimeField(default=datetime.datetime.now)
  • Do not forget to use a callable. In other words, don’t put the ending parenthesis on the now otherwise all your objects will get the same time when the class was parsed.

def save(self, **kwargs):
    """override save to set defaults""" 
    if self.pk:
        self.updated_at = datetime.datetime.now()

    super(Post, self).save(**kwargs)

How can I override ModelForms field definitions? Such as changing the widget or specifying field attributes?

Thank You! (58:05)

Comments
  1. Jannis LeidelJanuary 07, 2008 @ 11:50 AM

    Wow Michael, thanks for compiling this every week! This is very helpful!

  2. StuJanuary 07, 2008 @ 01:42 PM

    What? “auto_add” is deprecated? Good to know. I’m using that everywhere.

  3. Matthew WensingJanuary 08, 2008 @ 01:53 PM

    I am not a contributor to the gis branch, but I have been using it heavily for the last several months to develop a hyperlocal journalism site with lots of geospatial data. Anyway, just wanted to say so since you asked . . .

    Great podcast!

  4. EmptyJanuary 09, 2008 @ 11:25 AM

    Jannis: Thanks for the kind words.

    Matthew: Contact me at my email I’d like to have you discuss it.