Mar 28 2010

get_first_object_or_none shortcut for Django

Category: Django,Pythonvbmendes @ 10:48

I will talk about a shortcut I developed for the Django framework and always use in my apps. This code is aimed in making a quik shortcut to obtain the first object of a queryset if it exists or None otherwise.

It’s very useful when you want to display the last news in the first page of your website, but don’t want it to break if there isn’t one to show. It’s just a use case for such a code, but there are many more.

In the past I used to write something like this:

try:
    first_user = User.objects.all()[:1][0]
except IndexError:
    first_user = None

This is four lines to do a very simple task and I wanted to evolve this to use only one line of code. So I developed a function that do this to me. It’s inspired in the django.shortcuts.get_object_or_404. Let’s take a look at the code:

def get_first_object_or_none(queryset):
    try:
        return queryset[:1][0]
    except IndexError:
        return None

I’ve put this code in a module called shortcuts inside my project and now everytime I want to use it I can write this code:

from shortcuts import get_first_object_or_none
first_user = get_first_object_or_none(User.objects.all())

I think it’s a very good result and helps a lot in my coding. It also made my code more legible and easy to understand. It increased my productivity and I am publishing to increase others productivity also. Any doubts, questions os suggestions, please leave a comment.

Tags: , , ,

10 Responses to “get_first_object_or_none shortcut for Django”

  1. Kenny Meyer says:

    Discovered a little error:

    from shortcuts import get_first_object_or_none -first_user = get_first_object_or_none(User.object.all()) +first_user = get_first_object_or_none(User.objects.all())

    Neat articles btw!

  2. lukasz says:

    In last code snippet there should be

    first_user = get_first_object_or_none(User.objects.all())

    in the second line (note there is ‘s’ in queryset.

    I would even go further and check if passed argument is an instance of QuerySet, if not, check if it’s a django.db.models.Model instance and if so, span default queryset. That should be easy, and your codes may be even cleaner.

    Similar functionality is available in SQLAlchemy for long time now and maybe this shortcut should land in Django, too?

    Take care

  3. Adam | Web Developer says:

    I’d enjoy seeing this put into Django. Nice, handy code.

  4. vbmendes says:

    Thanks Kenny and lukasz. I already fixed this little typo. Hoping that Django core implement this in django ORM, we could also override the QuerySet creating a method for this inside it. Maybe this is a better solution.

  5. Eric says:

    Why not just use latest()? As is, you’re relying on having an ordering set in the default model Meta. I would change your code to:

    def get_latest_or_none(model): try: return model.objects.latest() except model.DoesNotExist: return None

    used by:

    latest_object = get_latest_or_none(MyModel)

    If you still wanted to pass in querysets, you could easily adapt it.

  6. vbmendes says:

    @Eric

    Your suggestion is good, but your can’t order by fields that isn’t dates. In my example, I use the last new, but the code can also be used ordered by name or any other field.

    I prefer using queryset because almost all the times I use some filters on it.

  7. Marcin Nowak says:

    I think you can use builtin defaultfilters.first:

    from template.defaultfilters import first first_post = first(Post.objects.all())

    To display latest news on homepage simply use queryset ordering with slice/first template filter:

    context = {‘news’: Post.objects.recent(),}

    {% for post in news|slice:”:5″ %} … or {% with news|first as post %}{% if post %} ….

  8. Recuperar Archivos Formateados says:

    Me sirvió mucho leer este artículo y los comentarios de los demás. Suerte!

  9. Kelly Netzley says:

    I just would like to emphasize the very good work on this blog, has great views along with a clear vision of what you are looking for.

  10. Bob Schuon says:

    THIS is the kind of thing Django needs more of! Simple and clean, and you can remember it! One tiny suggestion, if I may? make the function get_first_object_or_None(), with the capital “N” to match the annoying get_object_or_None() function? Great idea, and it’s already added to my function list!

Leave a Reply