Django

N+1 Nightmare Busters

Today we're diving into two fantastic bug fixes that landed in Django - one preventing sneaky N+1 queries in RelatedManager with only(), and another fixing test crashes when running subset tests. Both PRs showcase the community's dedication to making Django more reliable and performant.

Duration: PT4M6S

https://podlog.io/listen/django-b4aa223e/episode/n-1-nightmare-busters-a35f9c64

Transcript

Hey there, Django developers! Welcome back to another episode of the Django podcast. I'm your host, and I'm genuinely excited to share what's been happening in the Django world today, January 14th, 2026.

You know that feeling when you think your code is running smoothly, and then you discover it's been silently making hundreds of database queries behind your back? Well, today we're talking about two brilliant fixes that tackle exactly these kinds of sneaky issues that can drive us all a little crazy.

Let's start with the star of the show - PR 20495 by Samriddha9619. This one's a real performance hero, fixing issue 35442 about N+1 queries in RelatedManager when using the only() method. Now, if you've ever used only() to optimize your queries by selecting just the fields you need, you might have unknowingly walked into this trap.

Here's what was happening: when you'd use only() and exclude the foreign key field, Django's ModelIterable would try to be helpful by accessing that foreign key on the child object to populate relationships. But since that key was deferred, every single access triggered a separate SQL query. Imagine iterating over a hundred objects and accidentally firing off a hundred extra database hits - ouch!

The fix is actually quite elegant. Instead of blindly accessing the foreign key attribute, Django now checks the object's dictionary first. If the foreign key isn't there because it was deferred, it gracefully handles the situation without triggering those expensive database roundtrips. It's one of those changes that makes you think "why didn't we think of this sooner?" - which is often the mark of a really good fix.

Our second merged PR comes from jacobtylerwalls, tackling issue 35402. This one's about fixing crashes in DatabaseFeatures.django_test_skips when running subset tests. Now, this might sound super technical, but it's actually solving a really practical problem that anyone running Django's test suite has probably bumped into.

The issue was with how Django was handling module imports in its test skipping machinery. The old implementation was sending module names to import_string(), but this relied on some fragile behavior where parent modules needed to already be imported. When you're running just a subset of tests, you can't guarantee that those parent modules have been loaded, leading to crashes.

The fix makes the import process more robust and reliable, so you can run your test subsets without worrying about mysterious import-related crashes. It's exactly the kind of developer experience improvement that makes your daily workflow just a little bit smoother.

Both of these changes really highlight something I love about the Django community - the attention to detail and the commitment to not just fixing bugs, but understanding the underlying problems and solving them thoughtfully. These aren't quick patches; they're considered solutions that make Django more reliable for everyone.

What's particularly encouraging is seeing contributors like Samriddha9619 and jacobtylerwalls diving deep into Django's internals and emerging with solid fixes. The collaborative process really shows too - with reviews, discussions, and iterations that strengthen the final solution.

So what's our focus for today? First, if you're using only() in your Django queries - and you should be for performance optimization - take a moment to celebrate that it just got even better. Second, if you've been frustrated by test-related import issues, those days are behind you.

But more broadly, these fixes remind us why it's so valuable to stay current with Django updates. Performance improvements and reliability fixes like these accumulate over time, making your applications faster and more stable without you having to change a single line of your own code.

That's a wrap for today's episode! Keep building amazing things with Django, keep contributing to this wonderful community, and I'll catch you tomorrow with more updates from the Django world. Until then, happy coding!