<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Query Optimization on Johnny Metz</title>
    <link>https://dev.johnnymetz.com/tags/query-optimization/</link>
    <description>Recent content in Query Optimization on Johnny Metz</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Mon, 19 Jan 2026 00:00:00 -0700</lastBuildDate>
    <atom:link href="https://dev.johnnymetz.com/tags/query-optimization/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Django Time-Based Lookups: A Performance Trap</title>
      <link>https://dev.johnnymetz.com/posts/django-time-based-lookups-performance/</link>
      <pubDate>Mon, 19 Jan 2026 00:00:00 -0700</pubDate>
      <guid>https://dev.johnnymetz.com/posts/django-time-based-lookups-performance/</guid>
      <description>&lt;p&gt;Django&amp;rsquo;s &lt;a href=&#34;https://docs.djangoproject.com/en/6.0/topics/db/queries/#field-lookups-intro&#34;&gt;&lt;code&gt;field lookups&lt;/code&gt;&lt;/a&gt; are one of the ORM&amp;rsquo;s best features, but time-based lookups can quietly bypass database indexes, turning fast queries into expensive full table scans.&lt;/p&gt;
&lt;h2 id=&#34;a-slow-production-query&#34;&gt;A Slow Production Query&lt;/h2&gt;
&lt;p&gt;I ran into this while debugging a 30 second query on a large table (~25 million rows):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Event&lt;/span&gt;(models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    timestamp &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;DateTimeField(db_index&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Event&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;filter(timestamp__date&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;datetime&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;date(&lt;span style=&#34;color:#ae81ff&#34;&gt;2026&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;))&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;count()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It generates SQL like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;COUNT&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; event
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;timestamp&lt;/span&gt;::date&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2026-01-05&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At first glance, it looked totally reasonable — a simple filter on an indexed field. But after checking the query plan, I discovered the issue: the query can&amp;rsquo;t use the index and falls back to a full table scan because it casts the field to a date.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Avoiding Duplicate Objects in Django Querysets</title>
      <link>https://dev.johnnymetz.com/posts/avoiding-duplicate-objects-in-django-querysets/</link>
      <pubDate>Sat, 03 Jan 2026 00:00:00 -0700</pubDate>
      <guid>https://dev.johnnymetz.com/posts/avoiding-duplicate-objects-in-django-querysets/</guid>
      <description>&lt;p&gt;When filtering Django querysets across relationships, you can easily end up with duplicate objects in your results. This is a common gotcha that happens with both one-to-many (1:N) and many-to-many (N:N) relationships. Let&amp;rsquo;s explore why this happens and the best way to avoid it.&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;When you filter a queryset by traversing a relationship, Django performs a SQL JOIN. If a parent object has multiple related objects that match your filter, the parent object appears multiple times in the result set.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Speed Up Django Queries with values() over only()</title>
      <link>https://dev.johnnymetz.com/posts/django-values-over-only/</link>
      <pubDate>Sun, 29 Jun 2025 13:11:26 -0700</pubDate>
      <guid>https://dev.johnnymetz.com/posts/django-values-over-only/</guid>
      <description>&lt;p&gt;If your Django queries feel slow, the problem might not be your database — it might be your ORM. Recently, I was working with a query that took 25 seconds to run through the Django ORM, but the underlying SQL completed in just 2 seconds. With a single change, I got the ORM query down to 2 seconds as well — and reduced the memory footprint by 70%.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s walk through what happened, and why using &lt;code&gt;.values()&lt;/code&gt; instead of &lt;code&gt;.only()&lt;/code&gt; can dramatically improve performance.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Avoiding PostgreSQL Pitfalls: The Hidden Cost of Failing Inserts</title>
      <link>https://dev.johnnymetz.com/posts/postgresql-failing-insert/</link>
      <pubDate>Sun, 15 Jun 2025 18:00:00 -0700</pubDate>
      <guid>https://dev.johnnymetz.com/posts/postgresql-failing-insert/</guid>
      <description>&lt;p&gt;A simple insert query turned into a silent performance killer.&lt;/p&gt;
&lt;p&gt;Our frontend pings our server every few minutes to track device activity. Each ping attempts to insert a row into a &lt;code&gt;DevicePingDaily&lt;/code&gt; table, which has a unique constraint on &lt;code&gt;(device_id, date)&lt;/code&gt; to ensure only one record per device per day.&lt;/p&gt;
&lt;p&gt;In Django, the logic looked like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    DevicePingDaily&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;create(device&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;device, date&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;today)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;except&lt;/span&gt; IntegrityError:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It seemed harmless. But as traffic grew, latency spiked and API timeouts increased. Observability tools quickly pointed to the culprit:&lt;/p&gt;</description>
    </item>
    <item>
      <title>5 Ways to Get the Latest Book Per Author in Django</title>
      <link>https://dev.johnnymetz.com/posts/latest-book-per-author/</link>
      <pubDate>Thu, 14 Nov 2024 12:00:00 -0700</pubDate>
      <guid>https://dev.johnnymetz.com/posts/latest-book-per-author/</guid>
      <description>&lt;p&gt;In a Django application, fetching the latest record for each group is a common yet challenging task, especially when working with large datasets. Whether you&amp;rsquo;re building an analytics dashboard or managing grouped data, finding an efficient solution is key. In this blog post, we&amp;rsquo;ll explore five different approaches to tackle this problem, ranked from least to most effective based on performance and readability, using the following &lt;code&gt;Book&lt;/code&gt; model:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Book&lt;/span&gt;(models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    title &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    author &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;ForeignKey(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Author, on_delete&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CASCADE, related_name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;books&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    genre &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    published_at &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;DateTimeField()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    is_featured &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;BooleanField(default&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;solution-1-python-max-with-prefetch&#34;&gt;Solution 1: Python Max with Prefetch&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;latest_books &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    max(author&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;books&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;all(), key&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: x&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;published_at, default&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; author &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; Author&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;prefetch_related(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;books&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Performs heavy computation in Python rather than leveraging the database, which is &lt;a href=&#34;https://docs.djangoproject.com/en/5.1/topics/db/optimization/#do-database-work-in-the-database-rather-than-in-python&#34;&gt;bad for performance&lt;/a&gt;. Also makes two database queries (better solutions do it in one).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Supercharge Your Django App: 7 Sneaky Tricks to Crush Slow Database Queries</title>
      <link>https://dev.johnnymetz.com/posts/slow-django-database-queries/</link>
      <pubDate>Sun, 13 Aug 2023 12:15:13 -0400</pubDate>
      <guid>https://dev.johnnymetz.com/posts/slow-django-database-queries/</guid>
      <description>&lt;p&gt;Optimizing Django query performance is critical for building performant web applications. Django provides many tools and methods for optimizing database queries in its &lt;a href=&#34;https://docs.djangoproject.com/en/4.2/topics/db/optimization/&#34;&gt;Database access optimization documentation&lt;/a&gt;. In this blog post, we will explore a collection of additional and essential tips I&amp;rsquo;ve compiled over the years to help you pinpoint and resolve your inefficient Django queries.&lt;/p&gt;
&lt;h2 id=&#34;kill-long-running-queries-with-a-statement-timeout&#34;&gt;Kill Long-Running Queries with a Statement Timeout&lt;/h2&gt;
&lt;p&gt;PostgreSQL supports a &lt;a href=&#34;https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-STATEMENT-TIMEOUT&#34;&gt;&lt;code&gt;statement_timeout&lt;/code&gt;&lt;/a&gt; parameter that allows you to set a maximum time limit per query. This is useful for preventing long-running queries from tying up precious resources and slowing down your application. My team at &lt;a href=&#34;https://www.pixiebrix.com/&#34;&gt;PixieBrix&lt;/a&gt; experienced an incident where a few long-running queries resulted in a full database outage. Setting a statement timeout in your Django settings can help prevent this from happening.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Optimize Django Query Performance by combining Select Related and Prefetch Related</title>
      <link>https://dev.johnnymetz.com/posts/combine-select-related-prefetch-related/</link>
      <pubDate>Sat, 13 May 2023 15:48:39 -0400</pubDate>
      <guid>https://dev.johnnymetz.com/posts/combine-select-related-prefetch-related/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;When building a Django application, one of the key challenges developers face is optimizing database query performance. Django provides two tools,&lt;code&gt;select_related&lt;/code&gt; and &lt;code&gt;prefetch_related&lt;/code&gt;, that reduce the number of database queries, and increase the performance of your application.&lt;/p&gt;
&lt;p&gt;This blog post explores the power of these two methods and how to combine them to maximize your application&amp;rsquo;s query performance.&lt;/p&gt;
&lt;p&gt;My team at &lt;a href=&#34;https://www.pixiebrix.com/&#34;&gt;PixieBrix&lt;/a&gt; implemented these techniques and have seen a significant improvement in query performance and customer satisfaction.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sort a Django Queryset by a Custom Order</title>
      <link>https://dev.johnnymetz.com/posts/sort-django-queryset-by-custom-order/</link>
      <pubDate>Mon, 02 Jan 2023 17:00:00 -0800</pubDate>
      <guid>https://dev.johnnymetz.com/posts/sort-django-queryset-by-custom-order/</guid>
      <description>&lt;p&gt;Sorting a Django queryset by a custom order is trickier than it looks, and choosing the wrong solution for your use case can cripple your application&amp;rsquo;s performance.&lt;/p&gt;
&lt;p&gt;For example, let’s take a simple &lt;code&gt;Todo&lt;/code&gt; model:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Todo&lt;/span&gt;(models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Priority&lt;/span&gt;(models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;TextChoices):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        HIGH &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;HIGH&amp;#34;&lt;/span&gt;, _(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;High&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        MEDIUM &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;MEDIUM&amp;#34;&lt;/span&gt;, _(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Medium&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LOW &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;LOW&amp;#34;&lt;/span&gt;, _(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Low&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    title &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    priority &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, choices&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;Priority&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;choices, db_index&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    done &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;BooleanField(default&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And a list of todos:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Id&lt;/th&gt;
					&lt;th&gt;Title&lt;/th&gt;
					&lt;th&gt;Priority&lt;/th&gt;
					&lt;th&gt;Done&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;Add linters&lt;/td&gt;
					&lt;td&gt;Medium&lt;/td&gt;
					&lt;td&gt;Yes&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;Fix bug&lt;/td&gt;
					&lt;td&gt;High&lt;/td&gt;
					&lt;td&gt;No&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;Increase test coverage&lt;/td&gt;
					&lt;td&gt;Medium&lt;/td&gt;
					&lt;td&gt;No&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;4&lt;/td&gt;
					&lt;td&gt;Refactor views&lt;/td&gt;
					&lt;td&gt;Low&lt;/td&gt;
					&lt;td&gt;No&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;Run tests in CI&lt;/td&gt;
					&lt;td&gt;High&lt;/td&gt;
					&lt;td&gt;Yes&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Our query set goal is to order these items from high to low &lt;code&gt;priority&lt;/code&gt;. For priority levels with multiple items, we&amp;rsquo;ll also order by &lt;code&gt;title&lt;/code&gt; to keep the results consistent. The expected result should be the id’s in the following order: &lt;code&gt;[2, 5, 1, 3, 4]&lt;/code&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>5 ways to get all Django objects with a related object</title>
      <link>https://dev.johnnymetz.com/posts/five-ways-to-get-django-objects-with-a-related-object/</link>
      <pubDate>Fri, 01 Oct 2021 13:08:48 -0700</pubDate>
      <guid>https://dev.johnnymetz.com/posts/five-ways-to-get-django-objects-with-a-related-object/</guid>
      <description>&lt;p&gt;In Django, a &lt;a href=&#34;https://docs.djangoproject.com/en/3.2/ref/models/relations/&#34;&gt;related object&lt;/a&gt; is a model instance used in the one-to-many or many-to-many context.&lt;/p&gt;
&lt;p&gt;For example, let&amp;rsquo;s look at the built-in &lt;code&gt;User&lt;/code&gt; model, which has a many-to-many relationship with the &lt;code&gt;Group&lt;/code&gt; model.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;User&lt;/span&gt;(models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    groups &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;ManyToManyField(Group, related_name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;groups&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For any given &lt;code&gt;User&lt;/code&gt; object, all linked &lt;code&gt;Group&lt;/code&gt; objects are called &amp;ldquo;related objects&amp;rdquo;. Here are 5 ways to fetch all &lt;code&gt;User&lt;/code&gt; objects with at least one related &lt;code&gt;Group&lt;/code&gt; object.&lt;/p&gt;
&lt;h2 id=&#34;iterate-over-each-object-in-python&#34;&gt;Iterate over each object in Python&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;users &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; user &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; User&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;prefetch_related(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;groups&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; user&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;groups&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;exists():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        users&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(user)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Probably the most popular approach but there are two problems:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why you need to use Subqueries in Django</title>
      <link>https://dev.johnnymetz.com/posts/why-you-need-to-use-django-subqueries/</link>
      <pubDate>Wed, 21 Jul 2021 11:56:09 -0700</pubDate>
      <guid>https://dev.johnnymetz.com/posts/why-you-need-to-use-django-subqueries/</guid>
      <description>&lt;p&gt;The Django ORM is a powerful tool but certain aspects of it are counterintuitive, such as the SQL order of execution.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at an example of this trap and how we can fix it using subqueries:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Book&lt;/span&gt;(models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Meta&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        constraints &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;UniqueConstraint(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                fields&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;edition&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;%(app_label)s&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;_&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;%(class)s&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;_unique_name_edition&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    edition &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    release_year &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;PositiveIntegerField(null&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I want to write a query that reads:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Find all N&#43;1 violations in your Django app</title>
      <link>https://dev.johnnymetz.com/posts/find-nplusone-violations/</link>
      <pubDate>Tue, 13 Apr 2021 23:10:50 -0800</pubDate>
      <guid>https://dev.johnnymetz.com/posts/find-nplusone-violations/</guid>
      <description>&lt;p&gt;The N+1 problem is a common database performance issue. It plagues ORM&amp;rsquo;s, such as Django and SQLAlchemy, because it leads to your application making more database queries than necessary.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at a basic example in Django.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Artist&lt;/span&gt;(models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Song&lt;/span&gt;(models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    artist &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;ForeignKey(Artist, on_delete&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CASCADE)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;print_songs&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; song &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; Song&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;all():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;song&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;artist&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;name&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; - &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;song&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;name&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s create a unit test to ensure &lt;code&gt;print_songs&lt;/code&gt; runs successfully. We&amp;rsquo;re using &lt;code&gt;pytest&lt;/code&gt; and &lt;code&gt;pytest-django&lt;/code&gt; so we can create the test data using a &lt;a href=&#34;https://docs.pytest.org/en/stable/fixture.html&#34;&gt;pytest fixture&lt;/a&gt;. When we run the unit test, you&amp;rsquo;ll notice it passes and our songs are printed to the terminal. Everything seems fine on the surface.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
