This Week in Django 5 - 2008-01-06

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)
-
Chatting with Adrian Holovaty – Akita on Rails interview with Adrian Holovaty
Tracking Trunk (8:12)
-
Changeset
(6981)
– Made the{% for %}
tag a bit more efficient by creating a single context dictionary rather than recreating it each time through the loop.
-
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)
- Brian Rosner discusses the Queryset Refactor Branch.
Community Catchup (33:28)
- – Google Groups discussion about not getting a nice error page when an exception occurs in the middleware. A patch is forthcoming.
-
Django Tip: Complex Forms – Malcolm Tredinnick’s blog Defying Classification. Excellent piece on doing complex newforms work.
- Using the Django NewForms Library – Big Nerd Ranch Weblog
- Newforms, part 1 – James Bennett
- Newforms, part 2 – James Bennett
- Customizing NewForms – Michael Trier
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?
-
auto_now
andauto_now_add
are on their way out. See and . - Use the
default
option when defining the model - Django Documentation on
default
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.
- If you need to update the datetime every time then override the save method.
- Django Documentation on Overriding the Save Method
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?
- Django Documentation on Overriding Default Field Types
- Given a ModelForm that doesn’t define any fields, everything will be the default.
- If you define a field in your ModelForm class that has the same name as one that would be auto-generated it will override the default field.
- You can also override the
__init__
but I would only do that if you need to make dynamic runtime type modifications. - Django Screencast 4: NewForms Personalization