⟵back

Django ORM basics

Since starting my current job, I've found I need to brush up a bit on querysets and ORM (object-relational mapping). A queryset is a Python object that lets you view (Django) model instances through various filters or conditions. I thought it was enough to see the number of instances, get one, or get them in a certain order. But there's so much more to it than that.

Django ORM is so useful primarily for two reasons:

  1. It prevents you from having to make raw SQL queries on your database, i.e. not touching the database, just having a look at what's in there.
  2. In very large applications, filtering and using managers prevents you from having to query the whole database, or all the instances of a model — two ways you can significantly reduce performance.

It can be a little finicky to implement from memory. But then again, it's about understanding concepts, not ultimate knowledge.

Here are a few queryset examples, using the BlogPage class from this very blog. It's just a fraction of what's out there, but you can find out more in the official docs.

  • BlogPage.objects.all()
    Return all instances of BlogPage.

  • BlogPage.objects.filter(body__icontains='python')
    Return all BlogPage instances where body (i.e. the post itself) contains the string "python". Enter the desired attribute in the brackets, double underscore, icontains, then the string).

  • BlogPage.objects.filter(body__icontains='python').exists()
    Returns a Boolean value of whether at least one object meeting this criteria exists.

  • BlogPage.objects.filter(body__icontains='python').values()
    Returns each instance meeting the criteria in the form of a dictionary — in the case of BlogPage, keys include translation_key, latest_revision_created_at, and content_type_id.

  • BlogPage.objects.filter(body__icontains='python').count()
    Returns the number of objects meeting this criteria.

  • BlogPage.objects.filter(body__icontains='python').exclude(date__lt=datetime.date(2020, 01, 01))
    Returns criteria excluding any post published before 2020.