Best Practices for filter()[0] and get()

7 views
Skip to first unread message

Michael Burton

unread,
Feb 6, 2009, 6:14:37 PM2/6/09
to django...@googlegroups.com
I often have a need to get an object that I don't know for sure is in the database. For example,

  • Retrieving a person by username when the username may have been mistyped, eg. User.objects.get(...)
  • Retrieving a user's most recently used location, if they have one, eg. Location.objects.filter(...).order_by('-date')[0]
  • Get a user's recommendation for a restaurant, if they've made one. eg. Rec.objects.get(...)

Using django's filter() and get() methods seem a little awkward for these cases.  What I generally want is to get the specified object if it exists, otherwise get None. {1}

The best I've been able to come up with is something like the following:

x = (MyModel.objects.filter(...) or [None])[0]

Or maybe:

try:
    x = MyModel.objects.get(...)
except:
    x = None

Both of these work, but the first isn't very readable and the second is a bit verbose.  I've taken to wrapping the first one in a homegrown get_object_or_none() shortcut {2}, but I thought i'd check and see if anyone had any more graceful solutions.

Am I missing something easy and/or clever?  Does django have a nice way to do this that I'm just missing?  It would be super nice if I could just say something like MyModel.objects.get( x=y, default=None) {3}

Cheers,
Mike


{1} Note that django has a nice shortcut for the case where I want an object or 404.  The get_object_or_404() shortcut handles this for the very specific case where I want to throw a 404 if the object is not found.  This is often what I want, but also quite often NOT what I want.
{2} Which generally works, but isn't super flexible.  For example, it doesn't handle the Location example above, since there's no way to specify an order_by clause.
{3} More or less following the convention set by python's dict.get() method, where you can specify a result to return if the key is not in the dictionary.

Russell Keith-Magee

unread,
Feb 7, 2009, 12:15:58 AM2/7/09
to django...@googlegroups.com
On Sat, Feb 7, 2009 at 8:14 AM, Michael Burton <mi...@niskala.org> wrote:
> I often have a need to get an object that I don't know for sure is in the
> database. For example,
>
> Retrieving a person by username when the username may have been mistyped,
> eg. User.objects.get(...)
> Retrieving a user's most recently used location, if they have one, eg.
> Location.objects.filter(...).order_by('-date')[0]
> Get a user's recommendation for a restaurant, if they've made one. eg.
> Rec.objects.get(...)
>
> Using django's filter() and get() methods seem a little awkward for these
> cases. What I generally want is to get the specified object if it exists,
> otherwise get None. {1}

You're on the right track here. get_object_or_404 is a 6 line
shortcut; writing your own get_object_or_none is an equally simple 4
line shortcut. Django doesn't have one baked in, but if you find
yourself using this idiom a lot, it's not hard to produce one
yourself.

Regarding your second use case - you may want to look into the
latest() operator on queries:

http://docs.djangoproject.com/en/dev/ref/models/querysets/#latest-field-name-none

Yours,
Russ Magee %-)

Reply all
Reply to author
Forward
0 new messages