14 Apr 2026
Django community aggregator: Community blog posts
Representing 'Jobs to be Done' in a project
I have had this idea/theory for a while, that most software tools would benefit from a simple built in todo list built into the product directly. The main idea is for users to create jobs themselves or for the system itself to create jobs for the user to complete. The general thesis for this idea comes from a direct reference to the term "Jobs to be done". Any piece of software that gets used, exists to complete a job and do it better than the solution before it.
Well over the last couple of months I have turned this idea into a reality inside Hamilton Rock, or at least the first version of it and so far it seems very promising. The general API design is a few custom signals, a model and some signal reciever functions for the custom signals. The rest of the project interacts solely through the custom signals job_requested and job_completed. Each does as you would expect, job_requested requests a job be created, job_completed complete the related job to the model instance given. The core of the job model has a status, type and a generic foreign key which forms the target related to the job. Jobs can auto-completed when a condition has been met, it's just a matter of firing off the completed signal. Example stub of the API is below.
job_requested = Signal()
job_completed = Signal()
class Job(models.Model):
content_type = models.ForeignKey(
ContentType,
on_delete=models.CASCADE,
help_text=_("The type of object this job is related to"),
)
object_id = models.PositiveIntegerField(
help_text=_("The ID of the related object"),
)
target = GenericForeignKey("content_type", "object_id")
assigned_to = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="assigned_jobs",
help_text=_("User this job is assigned to (default notification recipient)"),
)
job_type = models.CharField(
max_length=50,
choices=jobTypeChoices.choices,
help_text=_("The type of job"),
)
status = models.CharField(
max_length=20,
choices=StatusChoices.choices,
default=StatusChoices.PENDING,
db_index=True,
help_text=_("Current status of the job"),
)
created_at = models.DateTimeField(
null=True,
blank=True,
help_text=_("When the job was completed or cancelled"),
)
updated_at = models.DateTimeField(
null=True,
blank=True,
help_text=_("When the job was completed or cancelled"),
)
completed_at = models.DateTimeField(
null=True,
blank=True,
help_text=_("When the job was completed or cancelled"),
)
expires_at = models.DateTimeField(
null=True,
blank=True,
db_index=True,
help_text=_("When this job should be auto-cancelled if still pending"),
)
metadata = models.JSONField(
default=dict,
blank=True,
help_text=_("Additional job-specific data"),
)
@receiver(job_requested)
def handle_job_requested( # NOQA: PLR0913
sender,
target,
job_type,
metadata=None,
idempotent=False,
assigned_to=None,
**kwargs,
):
# Creates a Job
pass
@receiver(task_completed)
def handle_task_completed(sender, target, task_type, metadata=None, **kwargs):
# Completes a Job
pass
Currently all jobs are created by the system and we have yet to directly expose them to our users, however there have been two interesting insights from where I have used them to date (onboarding & staff pages). First in onboarding it has created a flexible way to add/remove steps for me as a developer and given that completing a job is part of the internal state rather than just a custom form or series of forms, the logic to visualise where users are stalling in our flow becomes easy to visualise. It's how many pending jobs at each step and how long have they been pending?
Second when an handled exception case occurs in the application which requires the attention of a staff user, instead of a log statement needing to be processed by some system and being perhaps overfilled with extra context, or there being extra noise in a developer tool such as Sentry, we simply create a job of the type we need. Then create a staff page to list and handle jobs of this type.
Finally this jobs architecture has enabled a central point to control how we send notifications (emails etc) from the system. Every notification is linked to a Job, which then means it forces notifications to not deal with too many actions at a time and again allows a natural tracking of which notifications have been actioned or not.
In future, I'm likely to expose these jobs to our users more directly, giving them a native solution to spend just the right amount of time in our product and no more, so what we build is simple & useful.
What do you think? Would you like this as a package for you to play with? Let me know and I may just break it out and release it!
14 Apr 2026 5:00am GMT
13 Apr 2026
Django community aggregator: Community blog posts
Built with Django Weekly Roundup: Mar 23 to Apr 13
Hey, Happy Monday!
Why are you getting this: You signed up to receive this newsletter on Built with Django. I share recent projects, jobs, and useful Django links. If you no longer want this, you can unsubscribe anytime.
News and Updates
- This issue covers March 23rd through April 13th.
- I widened the window this time so we capture the full recent batch of good additions.
Sponsor
This issue is sponsored by TuxSEO, your content team on auto-pilot.
Generate SEO-focused content briefs and drafts faster, and ship consistently without the usual content bottlenecks.
Projects
- Master Grammar - English grammar learning platform with structured lessons and tests. Built for english learners to master their grammar and achieve TOEIC/IELTS score target.
- Echoflare Managed Services - Professional Managed IT Services for Toronto Businesses
- My IT Fleet - Advanced IT Service Hub with advanced ticket approval flow , IT Asset inventory tracking, and It Fleet health intelligence.
Jobs
- Backend Engineer at Twindo (Formerly Canvas) - Remote
- Lead Engineer (Backend) at Onos Health - Remote
- Fullstack Engineer (backend-leaning) at Pinwheel - Hybrid (NYC - Union Square)
- B2B SaaS) at Weave Bio - San Francisco (SF), Hybrid/Onsite 3 days/week
- Product Engineer at Baserow - Remote
- Senior Software Engineer at Ping Data Intelligence - Delhi, India
- Security Engineer at Authentik Security - Remote
- Senior Backend Engineer at Courted - NYC
- Software Engineer at RINSE - Remote
- TypeScript Engineer at Fusionbox - Remote
From the Community
- Comprehensive Guide to Building Web Applications with Django Framework | Code2night.com
- How to Structure a Django REST API for a Production SaaS (Beyond the Tutorial) | by Md Mojno Miya | Mar, 2026 | Medium
- Models & the Django Admin | www.joshfinnie.com
Support
You can support this project by using one of the affiliate links below. These are always going to be projects I use and love! No "Bluehost" crap here!
- Buttondown - Email newsletter tool I use to send you this newsletter.
- Readwise - Best reading software company out there. If you want to up your e-reading game, this is definitely for you! It also so happens that I work for Readwise. Best company out there!
- Hetzner - IMHO the best place to buy a VPS or a server for your projects. I'll be doing a tutorial on how to use this in the future.
- SaaS Pegasus - One of the best ways to quickstart your Django project. If you have a business idea but don't want to set up all the boring stuff (auth, payments, workers, etc.), this is for you!
13 Apr 2026 6:00pm GMT
11 Apr 2026
Django community aggregator: Community blog posts
djust 0.4.0 — The Developer Experience Release
djust 0.4.0 ships 30+ features focused on developer experience: flash messages, keyboard shortcuts, form recovery, scaffolding generators, debug tooling, and security hardening. Build real-time Django apps with less code than ever.
11 Apr 2026 5:00pm GMT