Skip to main content

Custom Managers in Django

I had to add a bit of functionality to the Old Dog Haven "Walk For Old Dogs" registration and sponsorship site today (feel free to sponsor me!), specifically a way for the good folks running the event to see an aggregate total of the sponsorship dollars by registrant.

Here's the Django models for Registrant and Sponsor:
Pretty straight-forward -- main thing to notice is that Sponsor has a foreign key relationship with Registrant as opposed to the other way around. And yes, in its current incarnation sponsors can only sponsor one registrant; if they want to sponsor multiple registrants they simply create another sponsor record. (It's agile baby -- release early and often! Multiple sponsorships can happen next year!)

While calculating the total sponsorship dollars by each registrant could be handled via the Django ORM, I decided to use the opportunity to execute SQL directly in a function in a custom manager.

You can read more about custom managers in the Django docs, but the short version is that when you call something like Foo.objects.all() the objects bit refers to the model's Manager class, and it has all sorts of default functionality built in allowing you to easily interact with your model.

Referring back to the Sponsor and Registrant model code above, notice that since we're using a custom model manager, in the Sponsor model I added the line objects = SponsorManager() to override the default model manager with the custom one for which we'll see the code below.

As with most things in Django, model managers are easily extended and overridden, and in this case I wanted to add a new function to the Sponsor manager to return a list of registrants with a sum of their sponsorship amounts. This was as simple as adding a SponsorManager model that extends model.Manager and adding a function called with_sponsorship_totals to return the information I need.
Again, pretty straight-forward. SponsorManager extends models.Manager, we add the code to run the SQL query we want to execute, loop over the results and add instances of the Registrant model to the results list, and return the results.

One of the other great things I should point out about Python is the ability to add fields to classes on the fly. The Registrant class doesn't have a total_sponsorship_amount or team_name field defined, but I can add those as I loop over my results so they're available in the list returned by the custom manager function.

Another approach to solving this problem might be to add a function to the Registrant model itself that would calculate the total sponsorship amount for each registrant, but I opted to create a custom manager in this case to experiment a little, and I also thought it taking this approach would be more efficient than calculating individually for each registrant.

As you can see from this basic example, creating a custom manager for your Django models is an extremely simple, powerful way to add functionality to your application and is nothing to shy away from. By creating fat models and extending model managers where needed you can keep the business logic where it belongs and avoid a lot of unnecessary complexity in views and other areas of your application.

Comments

Popular posts from this blog

Installing and Configuring NextPVR as a Replacement for Windows Media Center

If you follow me on Google+ you'll know I had a recent rant about Windows Media Center, which after running fine for about a year suddenly decided as of January 29 it was done downloading the program guide and by extension was therefore done recording any TV shows.

I'll spare you more ranting and simply say that none of the suggestions I got (which I appreciate!) worked, and rather than spending more time figuring out why, I decided to try something different.

NextPVR is an awesome free (as in beer, not as in freedom unfortunately ...) PVR application for Windows that with a little bit of tweaking handily replaced Windows Media Center. It can even download guide data, which is apparently something WMC no longer feels like doing.

Background I wound up going down this road in a rather circuitous way. My initial goal for the weekend project was to get Raspbmc running on one of my Raspberry Pis. The latest version of XBMC has PVR functionality so I was anxious to try that out as a …

Running a Django Application on Windows Server 2012 with IIS

This is a first for me since under normal circumstances we run all our Django applications on Linux with Nginx, but we're in the process of developing an application for another department and due to the requirements around this project, we'll be handing the code off to them to deploy. They don't have any experience with Linux or web servers other than IIS, so I recently took up the challenge of figuring out how to run Django applications on Windows Server 2012 with IIS.

Based on the dated or complete lack of information around this I'm assuming it's not something that's very common in the wild, so I thought I'd share what I came up with in case others need to do this.


This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Assumptions and CaveatsThe operating system is Windows Server 2012 R2, 64-bit. If another variant of the operating system is being used, these instructions may not work properly.All of the soft…

Setting Up Django On a Raspberry Pi

This past weekend I finally got a chance to set up one of my two Raspberry Pis to use as a Django server so I thought I'd share the steps I went through both to save someone else attempting to do this some time as well as get any feedback in case there are different/better ways to do any of this.

I'm running this from my house (URL forthcoming once I get the real Django app finalized and put on the Raspberry Pi) using dyndns.org. I don't cover that aspect of things in this post but I'm happy to write that up as well if people are interested.

General Comments and Assumptions

Using latest Raspbian “wheezy” distro as of 1/19/2013 (http://www.raspberrypi.org/downloads)We’lll be using Nginx (http://nginx.org) as the web server/proxy and Gunicorn (http://gunicorn.org) as the WSGI serverI used http://www.apreche.net/complete-single-server-django-stack-tutorial/ heavily as I was creating this, so many thanks to the author of that tutorial. If you’re looking for more details on …