I recently have been dinging around in Django‘s ORM because I needed a certain ‘fields … group by’ selection. I was very impressed by the logic that the Django developers put in there. Especially the joins and aggregations that have been released with version 1.1. However, after a hours of testing and googling, I was not able to solve my problem with it. I needed a distinct selection like this:
SELECT id, name FROM myapp_model WHERE owner_id='1' GROUP BY name;
This would have been (easily) possible except for the WHERE clause on ownership that screwed me. Since the SQL statement was that simple I decided to write a bypass function that get’s the data straight from the database. It’s readonly access and I dont do anything more with it then create a list of links. Even more so, from a KISS point of view this code is easier to read back after several months.
And for reusability I turned it in to a function. It takes the model and the distinct field, and for my purpose the needed ownership as parameter:
from django.db import connection
def get_latest_objects(model_name=None, distinct_field=None, user_id=None):
""" Get lastest distinct selection (as tuples) of a given model
"""
model_name = model_name.lower()
query = ("select id,%(distinct_field)s from myapp_%(model_name)s "
"where owner_id='%(user_id)s' "
"group by %(distinct_field)s;") % {
'model_name': model_name,
'distinct_field': distinct_field,
'user_id': user_id,
}
cursor = connection.cursor()
cursor.execute(query)
There’s not much to it, I just hope it helps you to avoid ‘the hard way’. And it helps to keeps your view methods more readable because you dont need anything more then this:
latest_objects = get_latest_objects(model_name='MyModel',
distinct_field='name',
user_id=request.user.id)
What is returned (latest_objects) is a list of tuples that you can unpack in your templates straight away. Note that there’s no error checking in there, because I know what I’m doing 😉 Besides, worst case you get back an empty list and possible errors are caught when you write your tests. You do write those don’t you?
Grtz Gerard.