Django community: Community blog posts RSS
This page, updated regularly, aggregates Community blog posts from the Django community.
-
django-content-editor now supports nested sections
django-content-editor now supports nested sections django-content-editor (and it’s ancestor FeinCMS) has been the Django admin extension for editing content consisting of reusable blocks since 2009. In the last years we have more and more often started automatically grouping related items, e.g. for rendering a sequence of images as a gallery. But, sometimes it’s nice to give editors more control. This has been possible by using blocks which open a subsection and blocks which close a subsection for a long time, but it hasn’t been friendly to content managers, especially when using nested sections. The content editor now has first-class support for such nested sections. Here’s a screenshot showing the nesting: Finally it’s possible to visually group blocks into sections, collapse those sections as once and drag and drop whole sections into their place instead of having to select the involved blocks individually. The best part about it is that the content editor still supports all Django admin widgets, as long as those widgets have support for the Django administration interface’s inline form events! Moving DOM nodes around breaks attached JavaScript behaviors, but we do not actually move DOM nodes around after the initialization – instead, we use Flexbox ordering to … -
Django News - Python 3.13.0RC2 - Sep 13th 2024
News Python 3.13.0RC2 and security updates for 3.8 through 3.12 Python 3.13.0RC2 and security updates for Python 3.12.6, 3.11.10, 3.10.15, 3.9.20, and 3.8.20 are now available! blogspot.com DjangoCon US 2024 last call! DjangoCon US starts September 22nd. It's the last call to buy an in-person or online ticket to attend this year! ti.to Python in Visual Studio Code – September 2024 Release The Python extension now supports Django unit tests. microsoft.com Updates to Django Today 'Updates to Django' is presented by Raffaella Suardini from Djangonaut Space! Last week we had 12 pull requests merged into Django by 10 different contributors - including 4 first-time contributors! Congratulations to SirenityK, Mariatta, Wassef Ben Ahmed and github-user-en for having their first commits merged into Django - welcome on board! Last chance to apply for Djangonaut Space 🚀 The application will close on September 14, for more information check this article that explains the selection process. Apply here Django Newsletter Sponsored Link 1 HackSoft - Your Django Development Partner Beyond Code Elevate your Django projects with HackSoft! Try our expert consulting services and kickstart your project. hacksoft.io Articles Django from first principles, part 18 The final post in a series on building and refactoring … -
Cloud Migration Beginning - Building SaaS #202
In this episode, we started down the path of migrating School Desk off of Heroku and onto Digital Ocean. Most of the effort was on tool changes and beginning to make a Dockerfile for deploying the app to the new setup. -
Rescuing Django Projects with Smoke Tests: Quick Wins for Long-Term Success
We often inherit existing Django projects at Lincoln Loop either to provide ongoing maintenance or build new features (or both). Usually these projects are in some state of neglect and disrepair when they come to us. If they were a house, they might be on the verge of being condemned and require some urgent repairs to prevent a catastrophe. To make matters worse, the tests are usually non-existent or broken to start with. So how do you make changes and have some level of confidence that you aren’t breaking other things in the process? Writing a complete test suite from scratch would be a large (expensive) undertaking and one that would not deliver much in terms of immediate value. We use smoke tests. Smoke tests give you the maximum coverage with the minimum effort. Pick out the key views or API endpoints and test that they return a 200 status code. Got something that requires a login? Verify it returns a 302, 401, or similar. Here are a few examples of smoke tests in Django (also using the wonderful model-bakery library): from http import HTTPStatus from django.contrib.auth import get_user_model from django.tests import TransactionTestCase from django.urls import reverse from model_bakery import … -
Fall 2024 Podcast Relaunch
The Stack ReportLearnDjango.com Podcast Sponsorship Info django-unique-user-email, neapolitan, and django-template-partialsawesome-django and djangox django-allauth Tutorial Carlton on Fosstodon and Will on Fosstodon -
Weeknotes (2024 week 37)
Weeknotes (2024 week 37) django-debug-toolbar alpha with async support! I have helped mentoring Aman Pandey who has worked all summer to add async support to django-debug-toolbar. Tim has released an alpha which contains all of the work up to a few days ago. Test it! Let’s find the breakages before the final release. Dropping Python 3.9 from my projects I have read Carlton’s post about the only green Python release and have started dropping Python 3.9 support from many of the packages I maintain. This is such a good point: […] I’m also thinking about it in terms of reducing the number of Python versions we support in CI. It feels like a lot of trees to support 5 full versions of Python for their entire life. 🌳 Releases django-debug-toolbar 5.0.0a0: See above. form-designer 0.26.2: The values of choice fields are now returned as-is when sending mails or exporting form submissions instead of only returning the slugified version. django-authlib 0.17.1: The role-based permissions backend had a bug where it wouldn’t return all available permissions in all circumstances, leading to empty navigation sidebars in the Django administration. This has been fixed. feincms3 5.2.3: Bugfix release, the page moving interface is no … -
Django-allauth: Site Matching Query Does Not Exist
Have you tried installing [django-allauth](https://docs.allauth.org/en/latest/) and encountered this particular error? I did, too, recently, and I've been successfully using `django-allauth` for years, so … -
Django: hoist repeated decorator definitions
Django provides us with a rich set of view decorators. In this post, we’ll look at a technique for hoisting repeated use of these decorators to reduce repetition. Repeated @cache_control calls Here are two public views with the same @cache_control decorator: from django.views.decorators.cache import cache_control @cache_control(max_age=60 * 60, public=True) def about(request): ... @cache_control(max_age=60 * 60, public=True) def contact_us(request): ... To avoid this repetition, we can call cache_control once at the top of the module and use that result as the decorator: from django.views.decorators.cache import cache_control cache_public = cache_control(max_age=60 * 60, public=True) @cache_public def about(request): ... @cache_public def team(request): ... This works because cache_control is technically not a decorator but a function that returns a decorator. So we can separate the call of cache_control from the decorating. Aside from reducing redundant repetition, this technique also saves a tiny bit of time and memory when importing the module, because cache_control is only called once. Repeated @require_http_methods calls Here’s another example, instead using @require_http_methods: from django.views.decorators.http import require_http_methods require_GET_POST = require_http_methods(("GET", "POST")) @require_GET_POST def contact_us(request): ... @require_GET_POST def store_feedback(request): ... (Actually, it would be neat if Django provided require_GET_POST out of the box…) Hoisting @method_decorator calls for class-based views This technique is particularly … -
django-filter: filtering a foreign key model property
django-filter is a fantastic library that makes easy to add complex filters in Django. While it requires very little code to get up and running, it can be a bit tricky to figure out how to do more non-standard things, like for example filtering against a foreign key model property. In this brief post we'll see with an example how I've achieved this. The models Consider two simple Django models, Book and Author: from django.db import models class Book(models.Model): title = models.CharField(max_length=100) author = models.ForeignKey("Author", on_delete=models.CASCADE) def __str__(self): return self.title class Author(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) @property def full_name(self): return f"{self.first_name} {self.last_name}" def __str__(self): return self.full_name Book has a ForeignKey to Author, and Author has a full_name property that returns the full name of the author. My use case is to be able to filter the Book list by the Author full_name property. Django filter would make easy to filter against a model field, that is, things that are actual database columns, like author__first_name or author__last_name, but filtering against a model property like author__full_name is not so straightforward. In other words, we would like to hit our page at /books/?author_full_name=clarke and get all the books written by Arthur … -
Django News - Django security releases issued: 5.1.1, 5.0.9, and 4.2.16 - Sep 6th 2024
News Django security releases issued: 5.1.1, 5.0.9, and 4.2.16 Two security fixes were just released. As always, the best security measure you can take is to always be on the latest version of Django. djangoproject.com Announcing Djangonaut Space Session 3 Applications Open! Session 3 applications are now open until September 14th. djangonaut.space Sponsored Link 1 Try Scout APM for free! Sick of performance issues? Enter Scout's APM tool for Python apps. Easily pinpoint and fix slowdowns with intelligent tracing logic. Optimize performance hassle-free, delighting your users. ter.li Articles Evolving Django’s auth.User Former Django Fellow Carlton Gibson has a lengthy and well-reasoned take on the auth.User model, pointing out its current limitations and forcefully arguing for some changes in future releases. buttondown.com Extending the Django OAuth Toolkit Application Model Mid-project Extending the Django OAuth Toolkit's application model mid-project can cause significant challenges, but Mariatta walks us through it. mariatta.ca Redis connections growing unbounded gunicorn+gevent and Celery can be tricky. There is a setting that is often missed that keeps your Redis connections from increasing until they reach the maximum. revsys.com Implementing Search with Django CMS 4 Learn how to implement custom search functionality on a Django CMS 4 site using Django … -
Kamal On A Droplet - Building SaaS #201
In this episode, we continued working with the Kamal deploy tool. Last time, we build a demo image. With this session, we created a Digital Ocean Droplet (i.e., VM) and deployed to that. Along the journey, we learned a lot about how Kamal operates. -
Django: a pattern for settings-configured API clients
Here’s an example of a common pattern in Django projects: from acme.api import APIClient from django.conf import settings acme_client = APIClient(api_key=settings.ACME_API_KEY) def order_anvil() -> None: acme_client.anvils.order(...) An API client is instantiated as a module-level variable based on some settings. This approach has some drawbacks: The client doesn’t get reinstantiated when settings change. This typically occurs during tests, where @override_settings would be useful: from django.test import TestCase, override_settings @override_settings(ACME_API_KEY="example-key") class ACMETests(TestCase): ... Tests instead need workarounds, like patching with unittest.mock.patch. Some API clients are expensive to instantiate, even issuing HTTP requests. This cost is paid at import time, thanks to module-level instantiation. This adds overhead to code paths that don’t use the client, such as unrelated management commands. Here’s an alternative pattern that avoids these problems: from functools import cache from acme.api import APIClient from django.conf import settings @cache def get_acme_client() -> APIClient: return APIClient(api_key=settings.ACME_API_KEY) @receiver(setting_changed) def reset_acme_client(*, setting, **kwargs): if setting == "ACME_API_KEY": get_acme_client.cache_clear() def order_anvil() -> None: get_acme_client().anvils.order(...) Notes: The client is now instantiated on first use, within get_acme_client(). This function is decorated with functools.cache, so the client is cached after the first call. A new signal receiver function, reset_acme_client(), resets the cache when the API key setting changes. … -
Django: build a Microsoft Teams bot
Recently, I built a Microsoft Teams bot for a client, inside their Django project. It wasn’t fun or easy, but the experience did increase my resiliency as a developer. I also went into this forewarned by my wife, a product manager also known as “the integration queen”, who has experienced the difficulties of the Teams API first-hand. I’m writing this post to leave some breadcrumbs for future adventurers braving this path. Issues that I encountered At the core, a Teams bot is a straightforward affair. Microsoft Teams sends HTTP requests to your webhook, to which your code should respond appropriately. Your bot can also send extra requests outside this cycle, to send messages or perform other actions. Unfortunately, there are a lot of complications to getting this process working. Here are some of the issues that I encountered: The documentation is a rat’s nest of competing terms, deprecations, and broken links. This seems to have been driven by rebranding the bot “product” and sub-products as AI and pitching for LLM-driven chatbots. For example, the Python package is referred to all of: “Bot Framework”, “Bot Framework SDK”, and “Bot Builder SDK”. And the Azure service for configuring a bot is called … -
Django Redirects App Tutorial
URL redirects are a fundamental part of maintaining a production website. There are many reasons _why_ you might want to redirect a user from one part of your website to … -
Why I Still Use Python Virtual Environments in Docker
Whenever I publish something about my Python Docker workflows, I invariably get challenged about whether it makes sense to use virtual environments in Docker containers. As always, it’s a trade-off, and I err on the side of standards and predictability. -
Django: avoid “useless use of .all()”
Here’s a little ORM pet peeve of mine that may deepen your understanding of how QuerySets work. Take this code: Digger.objects.all().filter(height_cm__gt=200) The .all() is unnecessary. It’s equivalent to write: Digger.objects.filter(height_cm__gt=200) Why? The manager, Digger.objects, already refers to all Digger objects. Calling .filter() creates a queryset from that manager, with some filtering. Add .all() only adds a useless copy of the queryset between these steps. You only need .all() in a few cases: To create a queryset that intentionally refers to all objects, perhaps for later filtering or slicing: diggers = Digger.objects.all() paginator = Paginator(diggers, 50) ... To delete all objects: Digger.objects.all().delete() Django requires the .all() as confirmation to prevent accidental deletion of a whole table. Useless calls to .all() aren’t a large problem, but they do mean more code to read and a slight performance cost for the extra queryset copies. I think that avoiding them also shows you understand ORM methods a little bit better. Fin May your querysets be lean and legible, —Adam -
Django News - DjangoCon Europe 2026 Call for Organizers - Aug 30th 2024
News Could you host DjangoCon Europe 2026? Call for organizers Posted by Thibaud Colas & DjangoCon Europe Support working group on August 28, 2024 djangoproject.com 10 years of attempting to make open source sustainable Reflecting on 10 years of trying to make open source sustainable readthedocs.com Python Developers Survey 2023 Results Official Python Developers Survey 2023 Results by Python Software Foundation and JetBrains: more than 25k responses from almost 200 countries. jetbrains.com What's new in pip 24.2 — or why legacy editable installs are deprecated A thorough write-up of what's new in pip 24.2 by a new core team member. github.io Updates to Django Today 'Updates to Django' is presented by Raffaella Suardini from Djangonaut Space! Last week we had 11 pull requests merged into Django by 9 different contributors - including 3 first-time contributors! Congratulations to Giovanni Fabbretti, Maarten Breddels and Clifford Gama for having their first commits merged into Django - welcome on board! News in Django 5.2: the function django.utils.html.format_html_join now supports taking an iterable of mappings, passing their contents as keyword arguments to django.utils.html.format_html. Django Newsletter Wagtail CMS Solving the messy middle: a simple block pattern for Wagtail CMS Examine a simple pattern for building block-based … -
Kamal - Building SaaS #200
In this episode, we pulled out a new tool. We spent the session using Kamal, a tool to deploy web apps directly to servers. Kamal offers a complete tool set to get apps running on bare metal or cloud machines. We played with the tool to see how far we go to get an app deployed to a new server. -
Django: rotate your secret key, fast or slow
Django’s SECRET_KEY setting is used for cryptographic signing in various places, such as for session storage and password reset tokens. This makes keeping it secure a high priority since an attacker with the key could forge things like password reset tokens. If you have leaked your secret key, you should rotate it. Committing it to your source code repository should count as a leak because it puts it in the hands of anyone who gains repository access in the future. Two options for rotating Django’s secret key are fast and forceful or slow and soft. Let’s look at them now after a quick tip. Generate a new secret key To make yourself a new secret key, you can use this undocumented-but-stable function from Django: In [1]: from django.core.management.utils import get_random_secret_key In [2]: get_random_secret_key() Out[2]: 'e4t-tdx$+(+d%-jy@d47&+gmohi8)3uwvjcc(fp4%n(jt4ur6v' This function is what Django uses to generate a secret key when you run startproject. Fast and forceful: change SECRET_KEY Use this path if you don’t mind these side effects: logging out all users losing all session data dropping all in-flight messages from the messages framework invalidating all in-progress password reset flows breaking any other uses of Django’s cryptographic signing, such as in django-sesame These … -
No Frills, Just Go: Standard Library Only Web Apps
How much can you build in Go with zero extra packages? What is possible using nothing more than Go’s standard library? In this talk, you’re going to find out! -
Weeknotes (2024 week 35)
Weeknotes (2024 week 35) Getting deep into htmx and django-template-partials I have been skeptical about htmx for some time because basically everything the library does is straightforward to do myself with a few lines of JavaScript. I am a convert now because, really, adding a few HTML attributes is nicer than copy pasting a few lines of JavaScript. Feels good. The combination of htmx with django-template-partials is great as well. I didn’t know I had been missing template partials until I started using them. Includes are still useful, but replacing some of them with partials makes working on the project much more enjoyable. I haven’t yet had a use for django-htmx but I may yet surprise myself. Releases django-authlib 0.17: django-authlib bundles authlib.little_auth which offers an user model which uses the email address as the username. I have also introduced the concept of roles instead of permissions; now I have reorganized the user admin fieldset to hide user permissions altogether. Group permissions are still available as are roles. I’m personally convinced that user permissions were a mistake. feincms3-forms 0.5: Allowed setting a maximum length for the bundled URL and email fields through the Django administration interface. django-content-editor 7.0.7: Fixed a … -
Production-ready Python Docker Containers with uv
Starting with 0.3.0, Astral’s uv brought many great features, including support for cross-platform lock files uv.lock. Together with subsequent fixes, it has become Python’s finest workflow tool for my (non-scientific) use cases. Here’s how I build production-ready containers, as fast as possible. -
There can't be only one
There’s a concept that I’ve heard called by a lot of different names, but my favorite name for it is “the Highlander problem”, which refers to the catchphrase of the campy-yet-still-quite-fun Highlander movie/TV franchise. In Highlander, immortal beings secretly live amongst us and sword-fight each other in hopes of being the last one standing, who will then get to rule the world forever. And when one of them is about to eliminate another, … Read full entry -
KISS Beats Accidental Complexity
Our friends at Sanvira published a blog post about a Django project they shipped five years ago, which is still running today without change, hand holding or application server restart. I really enjoy stories like this. Small, well engineered monoliths, just sitting there doing their job and not randomly breaking. While this sounds trivial it is not – and it is by far not the standard. I have seen enough systems fall apart for random reasons. Missing database indexes being on top of the list. The other thing that stands out to me are the frameworks and libraries. You can start nearly any web project with the exact same components today. (Ignoring VueJS - I reserve the right to not have an opinion on technologies and in domains I am not involved in.) APIs might have changed a bit. Functionality was added and bugs have been fixed. But they are all still around, doing well and have proven to be production ready. Compare that to ecosystems which reinvent package management every other week. -
Django Tailwind
This tutorial demonstrates how to configure Django and TailwindCSS from scratch in a new project. ## Django Setup Create a new virtual environment called `.venv`. ``` # Windows …