<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[75dev]]></title><description><![CDATA[75dev]]></description><link>https://blog.75dev.net</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1770289035622/337fdf32-622c-44f7-a031-962a3b59621f.png</url><title>75dev</title><link>https://blog.75dev.net</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 10:19:37 GMT</lastBuildDate><atom:link href="https://blog.75dev.net/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Exploring Django Tasks]]></title><description><![CDATA[Recap on where things stand
With the release of Django 6 and above, a new task framework has been introduced. Despite what some articles might suggest, this framework is not immediately beneficial for production environments and does not represent an...]]></description><link>https://blog.75dev.net/exploring-django-tasks</link><guid isPermaLink="true">https://blog.75dev.net/exploring-django-tasks</guid><category><![CDATA[Django]]></category><category><![CDATA[Python]]></category><category><![CDATA[celery]]></category><category><![CDATA[django-celery]]></category><dc:creator><![CDATA[James Shuttleworth]]></dc:creator><pubDate>Mon, 09 Feb 2026 13:49:13 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-recap-on-where-things-stand">Recap on where things stand</h1>
<p>With the release of Django 6 and above, a new task framework has been introduced. Despite what some articles might suggest, this framework is not immediately beneficial for production environments and does not represent an instant "game changer." Instead, it marks a positive step towards creating a back-end agnostic interface for queuing tasks.</p>
<p>Currently, the framework only includes a dummy and immediate back end. As a result, it does not serve as a replacement for established solutions like <a target="_blank" href="https://docs.celeryq.dev/en/stable/index.html">Celery</a>.</p>
<p>If all you want is a step-by-step guide to using named queues, skip down to “the quick guide to custom queues.” Everything else is just documenting my exploration in the hope it helps someone else get there faster.</p>
<h1 id="heading-django-tasks-and-django-tasks">Django Tasks and <code>django-tasks</code></h1>
<p>If you google for information, you’ll find the <a target="_blank" href="https://docs.djangoproject.com/en/6.0/topics/tasks/">Django documentation on tasks</a> as well as many tutorials that refer to the <a target="_blank" href="https://pypi.org/project/django-tasks/"><code>django-tasks</code></a> package.</p>
<p>The django-tasks package is an implementation (“backport” it is described as) that many tutorials refer to as a way to use a database back end and a way to run a task completion process. I can’t comment on whether this is “production ready”. The tutorials suggest “<code>manage.py db_worker</code>" as the way to run this, which feels like suggesting <code>manage.py runserver</code> is acceptable for production. But that’s for later exploration. At the moment, the docs say:</p>
<blockquote>
<p>Prior to <code>0.12.0</code>, <a target="_blank" href="https://github.com/RealOrangeOne/django-tasks-db"><code>django-tasks-db</code></a> and <a target="_blank" href="https://github.com/RealOrangeOne/django-tasks-rq"><code>django-tasks-rq</code></a> were also included to provide database and RQ based backends.</p>
</blockquote>
<p>So I’m not sure most of the search results for how to use Django tasks to run background tasks are valid at this point.</p>
<p>Everything in this article, though, is based on using the task framework built in to Django&gt;=6 but seems to be identical if you’re using the <code>django-tasks</code> package. And the <code>README.md</code> for <code>django-tasks</code> is really useful for understanding the basics.</p>
<h1 id="heading-queues">Queues</h1>
<p>I’m trying out the new task framework in a hobby project. I decided I would make use of the queuing system. At the moment I only have one kind of task, but I may add other tasks later just because it will be there and available.</p>
<p>There’s a note that if you change the queues enable you would get an <code>InvalidTaskError</code> exception. This caught me out because the phrasing is:</p>
<blockquote>
<p>Enqueueing tasks to an unknown queue name raises <code>InvalidTaskError</code>.</p>
</blockquote>
<p>My brain took that to mean that <strong>at the point of enqueueing, I would get an error</strong>. This is not the case.</p>
<p>So I added the section about queue names from the guide. At first this is not added to the <code>TASKS</code> settings dictionary. It also explains that in order "To disable queue name validation, set QUEUES to []." See below for more info on this below - I did some experimenting to ensure my understanding was correct before moving on, and it might be useful for others to see how that went.</p>
<pre><code class="lang-plaintext">django.tasks.exceptions.InvalidTask: Queue 'default' is not valid for backend.
</code></pre>
<p>This is not the same as the <code>InvalidTaskError</code> and I was a bit confused. The issue was, it turns out, that the decorator for the task function needs to specify the queue. As the file containing the task function is evaluated, the exception fires. I’m assuming the <code>InvalidTaskError</code> is somehow triggered if you enqueue some other way.</p>
<h2 id="heading-the-quick-guide-to-custom-queues">The quick guide to custom queues</h2>
<p>Everything else in this post is about my exploration - realisations, mistakes and thoughts included. But here is the quick guide to using custom queues with the task framework:</p>
<ol>
<li><p>Add the queue name to the <code>QUEUES</code> list in settings.</p>
</li>
<li><p>Decide if you want any existing task definitions to continue using the default queue. If so, make sure the <code>QUEUES</code> list also contains <code>”default”</code>.</p>
</li>
<li><p>Add the <code>queue_name</code> to the task decorator</p>
</li>
</ol>
<p>Here are the key pieces of code:</p>
<pre><code class="lang-python">
<span class="hljs-comment"># In settings.py</span>
TASKS = {
    <span class="hljs-string">"default"</span>: {
        <span class="hljs-string">"BACKEND"</span>: <span class="hljs-string">"django.tasks.backends.immediate.ImmediateBackend"</span>,
        <span class="hljs-string">"QUEUES"</span>: [
            <span class="hljs-string">"my_queue"</span>,
            <span class="hljs-comment">#Uncomment below to keep existing tasks using the default queue</span>
            <span class="hljs-comment">#"default",</span>
        ],
    }
}

<span class="hljs-comment"># In tasks.py</span>
<span class="hljs-keyword">from</span> django.tasks <span class="hljs-keyword">import</span> task

<span class="hljs-meta">@task(queue_name="my_queue")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">some_task</span>(<span class="hljs-params">id</span>):</span>
    <span class="hljs-string">"""Task for doing something with an object with given id"""</span>
    <span class="hljs-keyword">pass</span>
</code></pre>
<h1 id="heading-absence-of-queues-is-not-the-same-as-empty-queues">Absence of <code>QUEUES</code> is not the same as empty <code>QUEUES</code></h1>
<p>You can skip this section if you don’t care about how I proved to myself that I understood how queue validation worked.</p>
<p>From the <a target="_blank" href="https://github.com/RealOrangeOne/django-tasks/blob/master/README.md">django-tasks README.md</a> (at the time of writing: <a target="_blank" href="https://github.com/RealOrangeOne/django-tasks/blob/f3188b4f75a08a811204d30536d852cb7dd1ed28/README.md">09-02-2026</a>),</p>
<blockquote>
<p>"To disable queue name validation, set QUEUES to []."</p>
</blockquote>
<p>You might assume this means that without an explicit <code>QUEUES</code> list in the <code>TASKS</code> settings dict, there is no queue name validation but that’s not the case.</p>
<p>After I’d realised my mistake with the <code>queue_name</code> parameter, I experimented.</p>
<p>I figured there were multiple states of the <code>QUEUES</code> list that mattered. Not having one (1), having one with just the new queue name (2), having one with just “default” (3), having both (4) and having it as an empty list (5).</p>
<pre><code class="lang-python"><span class="hljs-comment"># 1</span>
TASKS = {
    <span class="hljs-string">"default"</span>: {
        <span class="hljs-string">"BACKEND"</span>: <span class="hljs-string">"django.tasks.backends.immediate.ImmediateBackend"</span>,
    }
}
<span class="hljs-comment"># 2</span>
TASKS = {
    <span class="hljs-string">"default"</span>: {
        <span class="hljs-string">"BACKEND"</span>: <span class="hljs-string">"django.tasks.backends.immediate.ImmediateBackend"</span>,
        <span class="hljs-string">"QUEUES"</span>: [
            <span class="hljs-string">"my_queue"</span>,
        ],
    }
}
<span class="hljs-comment"># 3</span>
TASKS = {
    <span class="hljs-string">"default"</span>: {
        <span class="hljs-string">"BACKEND"</span>: <span class="hljs-string">"django.tasks.backends.immediate.ImmediateBackend"</span>,
        <span class="hljs-string">"QUEUES"</span>: [
            <span class="hljs-string">"default"</span>,
        ],
    }
}
<span class="hljs-comment"># 4</span>
TASKS = {
    <span class="hljs-string">"default"</span>: {
        <span class="hljs-string">"BACKEND"</span>: <span class="hljs-string">"django.tasks.backends.immediate.ImmediateBackend"</span>,
        <span class="hljs-string">"QUEUES"</span>: [
            <span class="hljs-string">"default"</span>,
            <span class="hljs-string">"my_queue"</span>,
        ],
    }
}
<span class="hljs-comment"># 5</span>
TASKS = {
    <span class="hljs-string">"default"</span>: {
        <span class="hljs-string">"BACKEND"</span>: <span class="hljs-string">"django.tasks.backends.immediate.ImmediateBackend"</span>,
        <span class="hljs-string">"QUEUES"</span>: [],
    }
}
</code></pre>
<p>Then the task decorator could either not specify a queue (1), specify default (2) or specify a new queue name (3).</p>
<pre><code class="lang-python"><span class="hljs-comment"># 1</span>
<span class="hljs-meta">@task</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_task</span>(<span class="hljs-params">id</span>):</span>
    <span class="hljs-keyword">pass</span>

<span class="hljs-comment"># 2</span>
<span class="hljs-meta">@task(queue_name="default")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_task</span>(<span class="hljs-params">id</span>):</span>
    <span class="hljs-keyword">pass</span>

<span class="hljs-comment"># 3</span>
<span class="hljs-meta">@task(queue_name="my_queue")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_task</span>(<span class="hljs-params">id</span>):</span>
    <span class="hljs-keyword">pass</span>
</code></pre>
<p>As it happens, it seems 1 and 2 are identical, which makes sense. By default, the queue is “default”.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td></td><td>Default queue in decorator</td><td>Custom queue name in decorator</td></tr>
</thead>
<tbody>
<tr>
<td>No QUEUES setting</td><td>️✅</td><td>❌</td></tr>
<tr>
<td>Custom queue only</td><td>❌</td><td>️✅</td></tr>
<tr>
<td>Default queue only</td><td>️✅</td><td>❌</td></tr>
<tr>
<td>Default and custom queues</td><td>️✅</td><td>️✅</td></tr>
<tr>
<td>Empty QUEUE list</td><td>️✅</td><td>️✅</td></tr>
</tbody>
</table>
</div><h1 id="heading-where-does-this-leave-us">Where does this leave us?</h1>
<p>For my own exploration, I now have something that works with the new framework and I'm hopeful that with a combination of <code>django-tasks</code> and <code>django-tasks-db</code> I will have something that functions for background tasks. When I get to that point, I will have to dig into what might be safest for running in production. Can I really just use <code>db_runner</code>? Or will I have to roll my own task process? Or maybe there are other packages I can use to handle the tasks from the DB?</p>
<p>When I get time, I'll find out and post.</p>
]]></content:encoded></item><item><title><![CDATA[Too Many LLM Anecdotes Without Illustration]]></title><description><![CDATA[Lately, there has been an overwhelming number of articles discussing AI tools for developers. These articles often follow a familiar pattern: they speak in broad terms about AI's impact, either positively or negatively, but rarely provide concrete ex...]]></description><link>https://blog.75dev.net/too-many-llm-anecdotes-without-illustration</link><guid isPermaLink="true">https://blog.75dev.net/too-many-llm-anecdotes-without-illustration</guid><category><![CDATA[#qwen]]></category><category><![CDATA[agents]]></category><category><![CDATA[AI]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[cursor]]></category><category><![CDATA[cursor ai]]></category><dc:creator><![CDATA[James Shuttleworth]]></dc:creator><pubDate>Fri, 06 Feb 2026 13:56:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770491235206/7bbf95a6-8b23-4484-9261-fda0dd275ebd.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Lately, there has been an overwhelming number of articles discussing AI tools for developers. These articles often follow a familiar pattern: they speak in broad terms about AI's impact, either positively or negatively, but rarely provide concrete examples of how these tools are being utilized. Key details such as the specific tools being used, the costs involved, the problems being addressed, and the methods of evaluation are frequently omitted.</p>
<p>The comments on these articles also typically fall into three categories: those who found AI for coding to be ineffective, those who consider it revolutionary, and those who believe it is beneficial for specific tasks if applied correctly. However, these comments often lack clarity on the programming tasks being tackled, the platforms or services employed, the associated costs, and the evaluation processes and so on.</p>
<p>The insights from individuals experimenting with AI tools are incredibly valuable. Yet, without detailed information, it's challenging to extract more than a general understanding that there is a wide range of tasks, workflows, and tools that, when combined, produce varied outcomes.</p>
<p>It's unlikely that those who praise AI coding assistants do so merely because they are poor programmers. Similarly, it's improbable that those who dismiss AI tools simply don't know how to use them effectively. The notion that selective use of AI tools only addresses a specific class of programming problems also seems far-fetched.</p>
<h2 id="heading-apples-and-oranges">Apples and Oranges</h2>
<p>From the articles and comments, it's easy to assume people are disagreeing about AI as a programming support tool. But the reality is they are often only arguing for or against the tool they have used. There are people who are using suites provided by the big AI providers, such as <a target="_blank" href="https://cursor.com">Cursor</a>, while others are copying and pasting their files straight into <a target="_blank" href="https://chaton.ai/claude">Claude</a>, and everything in between.</p>
<p>There are <a target="_blank" href="https://arxiv.org/pdf/2507.09089">studies</a> that examine the efficacy of AI tools, which are intriguing but often lead to the same types of comments mentioned earlier. Additionally, many articles from AI companies lack thorough research and tend to be more about marketing than providing an open comparison of tools.</p>
<h2 id="heading-what-would-i-like-to-see">What Would I Like to See?</h2>
<p>What I'm really interested in is understanding what people are actually doing with these tools. What does their setup look like? What types of code is suitable for delegation to an LLM chat interface or agent? Are discussions about the performance of different models or modes useful, or is it the tooling that makes the significant difference?</p>
<h2 id="heading-moving-toward-more-deailed-discourse">Moving Toward More Deailed Discourse</h2>
<p>The rapid growth of AI programming tools and models indicates that we are still in the early stages of development. I hope we can eventually reach a level of discourse similar to that of platforms, frameworks, and languages. For instance, no one claims Rust is superior to Go simply because it feels better, nor do they promote a new framework just because it seems more nuanced and responsive compared to the current best-in-class.</p>
<p>There’s no real criticism intended here. I didn’t intend to write one of those “Everyone’s doing X wrong, and here’s why” articles. The whole point of this blog is trying to think and reason publicly, add to the conversation and consciously try to contribute.</p>
<p>I've been experimenting with <a target="_blank" href="https://github.com/QwenLM/qwen-code">Qwen Code</a> and could easily share my opinions on various forums without thinking about it as a data-point for others trying to work out how best to evaluate and use the newarray of tools at our disposal. However, I intend to document my experiences and findings in this blog instead. Perhaps others are seeking the same understanding I am, and my insights can contribute by providing semi-reproducible claims.</p>
]]></content:encoded></item><item><title><![CDATA[Finding real, useful info is hard]]></title><description><![CDATA[This isn’t about LLM-generated articles or rampant astroturfing. Those definitely contribute to the problem, but even without them, it can be hard to find good info on things. Especially if those things are software development.
TL;DR
Navigating the ...]]></description><link>https://blog.75dev.net/finding-real-useful-info-is-hard</link><guid isPermaLink="true">https://blog.75dev.net/finding-real-useful-info-is-hard</guid><category><![CDATA[Django]]></category><category><![CDATA[asynchronous]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Python]]></category><category><![CDATA[production-ready]]></category><category><![CDATA[documentation]]></category><dc:creator><![CDATA[James Shuttleworth]]></dc:creator><pubDate>Thu, 05 Feb 2026 09:57:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770491186914/0d2daf5c-0326-4528-bb99-cd4403f573e6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This isn’t about LLM-generated articles or rampant astroturfing. Those definitely contribute to the problem, but even without them, it can be hard to find good info on things. Especially if those things are software development.</p>
<h2 id="heading-tldr">TL;DR</h2>
<p>Navigating the vast sea of information available to software developers can be daunting, especially when seeking guidance that bridges the gap between beginner tutorials and advanced expertise. While the abundance of resources is undeniable, the challenge lies in discerning the truly valuable insights from the noise. By sharing experiences, engaging with the community, and documenting our learning journeys, we can contribute to a more comprehensive understanding of the tools and frameworks we use. This article is a step in that direction, aiming to spark conversations and encourage others to think aloud, explore publicly, and ultimately, enrich the collective knowledge of the developer community.</p>
<h2 id="heading-digital-natives">Digital Natives</h2>
<p>A friend and colleague and I used to give a talk together about how much information is available for people learning computer science and software engineering and yet people still need people to teach, guide and encourage them to become good software engineers and computer scientists. We talked about “digital natives” and how we used to believe that, any day now, a generation of learners would turn up to our seminars with all the basics covered, just from exposure to tech; and, how they never arrived. It was a fun talk that used the Wizard of Oz as a theme, which we stretched to fit in so many ways. Becoming all powerful, like Oz; pulling back the curtain; having what you needed all along; etc.</p>
<h2 id="heading-abundance-of-information">Abundance of Information</h2>
<p>It’s now many years later and I’ve spent much of that time both teaching software development (among other things) and doing commercial development work. In that time, the amount of freely available information for developers has grown, but mostly in one end of the spectrum or the other, but not the middle.</p>
<p>If you’re a beginner or advanced hobbyist, you’re covered. First steps in any language or with whatever library, infrastructure or framework is out there and you can follow any number of tutorials.</p>
<p>If you’re a developer working with a particular stack and you need API docs, blogs on trends or expert opinion on current architectures, you will find plenty.</p>
<h2 id="heading-the-missing-middle-ground">The Missing Middle Ground</h2>
<p>But what if you sit in the middle? For example, you’re a competent programmer but need to now build a web application. Or you’re a web developer that wants to switch to a new stack. The writing on how to go from a tutorial or quick test to something that is production-ready, makes use of modern best practices and utilises the best-in-class components is missing.</p>
<p>Worse, you often find writing that is incorrect and usually in a way that’s hard to spot from the wrong side of the learning curve.</p>
<h2 id="heading-an-example-djangos-new-task-framework">An Example: Django’s new Task Framework</h2>
<p>As an example, and the instance that triggered this post, try looking for information on Django’s new task framework. Before Django 6.0, if you wanted to have activity that was not synchronous with requests, you had to either build something separate and find a way to make it work with Django (put it in the DB, have the worker use it as a queue, set fields when done, have the web front end check status, etc.) or use something like <a target="_blank" href="https://docs.celeryq.dev/en/stable/">Celery</a>.</p>
<p>It makes sense for Django to fold some kind of asynchronous task framework into its core, just like it has done with other functionality. I don’t think Celery will stop being important (it’s a fully-fledged system with an amazing array of features) but it is overkill for lots of solutions.</p>
<p>The Django developers have created the framework but so far stayed away from implementing the actual back-end functionality. Some people argue that this is the wrong move, but I think it makes sense. It leaves room for others to create pluggable implementations of the back-end and doesn’t make them wait until there is a back-end ready and that comes with core Django. Plus whatever might fill that gap in core Django would become the de-facto back-end for many projects, even if the fit isn’t right.</p>
<p>Now, try looking for information on the new Django task framework. There’s the Django documentation, which is good and correct but not really a guide to having an asynchronous task system up and running. There are many posts that follow the usual pattern of explaining things by way of a tutorial application that doesn’t explain why things are as they are, how to make it production-ready, etc. And you also find articles talking about how it’s revolutionary. How now you just need core Django to have all your task needs met, ignoring the fact that core Django doesn’t actually have an asynchronous task completion back-end.</p>
<p>There’s also <a target="_blank" href="https://github.com/RealOrangeOne/django-tasks">Django Tasks</a> which is an “implementation and backport of background workers and tasks in Django“ but doesn’t come with “production-grade guarantees”. It’s great, and the docs are good <strong>if you know what you want</strong>.</p>
<h2 id="heading-the-role-of-community-and-personal-contribution">The Role of Community and Personal Contribution</h2>
<p>To be clear, I don’t think the Django developers or the Django Tasks package developers are failing to communicate. I like the idea of separation of concerns. Django tells you about Django and it’s not up to them to say how it fits your needs, same with Django Tasks. The problem is the proliferation of repetettive tutorial and opinion writing on the subject that’s masking information on how to understand the capability of the Django task framework.</p>
<p>And this is where someone should say “then write it”. And I might. But not until I feel confident I can not give people poor information myself. And maybe that’s the problem. By the time I know the task framework inside out, have found out which back-ends are useful, well written and production-ready, probably started writing a custom back end that I won’t ever complete but benefit from the journey of writing, I’ll have lost the perspective I currently have. I’ll only see the correct paths, not the indecision. I’ll instinctively design things to avoid the obvious (from my new perspective) pitfalls without realising it, making me unable to vocalise them for others.</p>
<h2 id="heading-moving-forward-thinking-and-exploring-publicly">Moving Forward: Thinking and Exploring Publicly</h2>
<p>This is where the past few days of thinking, reading and tinkering got me. This post isn’t the answer, but it is my first step toward providing something that is, I hope, helpful to someone, somewhere. I realised I used to find a lot of useful information on Stack Exchange, but that’s no longer the case. I find lots of good stuff on <a target="_blank" href="https://news.ycombinator.com/">Hacker News</a> and realised people visibly thinking about things was the real bonus. If there was more of that, I might find the record of someone who has already pondered similar problems and moved toward solutions, or solved the problem entirely. But more important than finding the lines of magic code that solves the issue is seeing how people think.</p>
<p>So, I now have a blog. It’s not my first. The others were all abandoned over the past few decades. This one might be abandoned in the future but for now I’m going to try to write down what could be useful for other people, while I’m in the middle of it.</p>
]]></content:encoded></item></channel></rss>