Django community: RSS
This page, updated regularly, aggregates Community blog posts from the Django community.
-
Weeknotes (2024 week 39)
Weeknotes (2024 week 39) CSS for Django forms Not much going on in OSS land. I have been somewhat active in the official Django forum, discussing ways to add Python-level hooks to allow adding CSS classes around form fields and their labels. The discussion on the forum and on the pull request goes in the direction of allowing using custom BoundField classes per form or even per project (instead of only per field as is already possible today). This would allow overriding css_classes, e.g. to add a simple class="field". Together with :has() this would probably allow me to skip using custom HTML templates in 99% of all cases. I have also been lurking in the Discord, but more to help and less to promote my packages and ideas :-) Releases django-user-messages 1.1: Added Django 5.0, 5.1 to the CI, and fixed the migrations to no longer mention index_together at all. It seems that squashing the migrations wasn’t sufficient, I also had to actually delete the old migrations. blacknoise 1.1: Starlette’s FileResponse has gained support for the HTTP Range header, allowing me to remove my homegrown implementation from the package. The blacknoise implementation is now half as long as it was … -
DjangoCon US 2024 - Short Summary
I apologize in advance for (1) the brevity, and (2) that not every talk is listed here. I didn't get a chance to watch them all yet. I do not mean any disrespect to any speaker who spoke, but is not listed here. Hopefully this can serve as a taste of the conference. I had a great time at DjangoCon US 2024, and I hope to see you next year! Day 1 Learning, Teaching Sheena O'Connell - Power to the People who Teach the People (Sheena's slides) "Make It Stick" by Peter C. Brown, Henry I. Roediger III, and Mark A. McDaniel. Mastery-based Learning Self-efficacy SPA vs Progressive Enhancement Chris May - Choosing Wisely: SPA vs. HTMX for Your Next Web Project "Progressive enhancement" means your site still works without JavaScript. The longer someone is on a page, the more likely a SPA would be useful. - 20+ operations on the same subset of data? - UI for chat or conversations? Katie Sylor-Miller's "Component Islands" explained in "Islands Architecture" by Jason Miller. The browser can handle a lot of things without JavaScript. Streamed HTML components Article series from Alex Russell on JavaScript excess. Packages: django-unicorn, htmx, alpinejs, django-template-partials, django-components, datastar, … -
Django News - 2024 Malcolm Tredinnick Prize nominations - Sep 20th 2024
News Nominate a Djangonaut for the 2024 Malcolm Tredinnick Memorial Prize Nominations are open until Monday, September 30th, 2024. Learn more about past winners here. djangoproject.com Last call for DjangoCon US 2024 tickets! It's the very last call for DjangoCon US 2024 tickets! djangoproject.com Django Software Foundation Could you host DjangoCon Europe 2026? Call for organizers We are looking for the next group of organizers to own and lead the 2026 DjangoCon Europe conference. djangoproject.com Updates to Django Today 'Updates to Django' is presented by Raffaella Suardini from Djangonaut Space! Last week we had 16 pull requests merged into Django by 8 different contributors - including 2 first-time contributors! Congratulations to khanxmetu and Gastón Avila for having their first commits merged into Django - welcome on board! News in Django 5.2: The new Model._is_pk_set() method allows checking if a Model instance’s primary key is defined. PR #18450 HttpRequest.accepted_types is now sorted by the client’s preference, based on the request’s Accept header.PR #18415 The new HttpRequest.get_preferred_type() method can be used to query the preferred media type the client accepts.PR #18415 Django 5.1.2 will also contain a fix for a regression that caused a crush when using the PostgreSQL lookup trigram_similar on … -
Docker Go, JS, Static Files - Building SaaS #203
In this episode, we continued on the cloud migration path. We need to build a Docker container with all the necessary static files. Some of these come from Go via Hugo for a content blog. Some comes from JavaScript via Tailwind for CSS. Some come from Python via Sphinx for documentation. All need to built into the same image. That’s what we covered on this stream. -
Docker Go, JS, Static Files - Building SaaS #203
In this episode, we continued on the cloud migration path. We need to build a Docker container with all the necessary static files. Some of these come from Go via Hugo for a content blog. Some comes from JavaScript via Tailwind for CSS. Some come from Python via Sphinx for documentation. All need to built into the same image. That’s what we covered on this stream. -
Django Fellows - Natalia Bidart & Sarah Boyce
Django Fellowship Program Django 5.1 Release Notes Natalia’s DjangoCon US Keynote Mastodon for Natalia and Sarah Django Core Demystified talk by Sarah Inside Out: DjangoCon US 2023 talk by Natalia Djangonaut Space DjangoCon US 2024 Contributing to DjangoDEP 0014: Background Workers Everything CurlSponsorDjango + HTMX Course at TalkPython Training 10% off -
Django: speed up tests slightly by disabling update_last_login
Django’s test client provides two methods to log in a user: login() and force_login(). The latter one is faster because it bypasses the authentication backend, including password hashing, and just sets a session to have the user logged in. Typically, you’d want to use it in setUp() like this: from http import HTTPStatus from django.test import TestCase class CornCobListViewTests(TestCase): @classmethod def setUpTestData(cls): cls.user = User.objects.create_user( username="testuser", password="12345", ) def setUp(self): self.client.force_login(self.user) def test_success(self): response = self.client.get("/cobs/") assert response.status_code == HTTPStatus.OK ... When profiling some client tests last week, I spotted that force_login() still took several milliseconds. Drilling down revealed that there was one query to create the session and another to update the user’s last_login field. This update comes from the update_last_login() function (source): def update_last_login(sender, user, **kwargs): """ A signal receiver which updates the last_login date for the user logging in. """ user.last_login = timezone.now() user.save(update_fields=["last_login"]) This receiver is conditionally registered in the django.contrib.auth app config (source): class AuthConfig(AppConfig): ... def ready(self): ... # Register the handler only if UserModel.last_login is a field. if isinstance(last_login_field, DeferredAttribute): from .models import update_last_login user_logged_in.connect(update_last_login, dispatch_uid="update_last_login") ... Well, an extra query per force_login() is not a big deal, but with several thousand tests, … -
PyUtrecht: FFIne, building foreign function interfaces - Marten Wijnja
(One of my summaries of the Dutch PyUtrecht meetup in Utrecht, NL). Full title: this is FFIne: building foreign function interfaces without shooting yourself in the foot. He works at channable (the host). They have both haskell and python codebases. Haskell is used for the more performance-critical code. They looked into using haskell from within python. With a foreign function interface. In some cases Haskell is faster. And it is handy to circumvent the "global interpreter lock" GIL. And sometimes there's a library for which there is no good alternative. Just so you know: many of the libraries you commonly use actually use another more system-oriented language under the hood. You need a host language: python, of course. And an embedded language that can compile to a dynamic library such as C, haskell and others. And third you need python's ctypes module. With ctypes you can load external libraries, including some necessary bookkeeping like input/output types. Behind the scenes, ctypes treats everything like C, including the problems iwth memory management, datatype mapping problems and undefined behaviour... The alternative to including such a libary via ctypes would be to running the other library in its own web server code and call … -
PyUtrecht: Repos are like children, parenting 101 - Bart Dorlandt
(One of my summaries of the Dutch PyUtrecht meetup in Utrecht, NL). Parenting and coding: choices have an effect. What is the outcome of your work? How does it turn out? But in the end you want to be proud of the outcome. You want your child/code to turn out right. With code, the effect of your decisions is clear reasonably quickly, with children it takes some more time. One repo turns into two repos and into three. And more. How do you keep them all the attention they deserve? How do you keep them up to date? Describe your child (=readme). Keep a journal (=changelog). Easy maintenance and easy to work with. Kids need boundaries. They need to know how to behave! Likewise, your code needs to behave: you need tests to set boundaries. After a while, your kid is old enough to go to school. Four years old or so. Hurray: you suddenly have more free time! Apparently your code is still alive! Potty training accomplished. Is your child/code ready to be shared with a wider public? But are you ready for others to make changes to your child? Some things are standard (or should be standard) for … -
PyUtrecht: Teaching yourself how to code - Joris Hoendervangers
(One of my summaries of the Dutch PyUtrecht meetup in Utrecht, NL). Joris started out as a bond trader, with his MSc in financial management. So definitively no programmer by education. Bond trading meant shouting on the stock market's floor, something that was in risk of being automated. So he moved on. In his case to Reuters, one of the two big financial information suppliers. Later he started using python and making nice prototypes, which clients loved. Now he's a python trainer ("PythonSherpa"). A bit of imposter syndrome was present when he was demoing some jupyter notebooks to expensive managers when he was still a python beginner. Later on as python trainer, imposter syndrome was still a thingy. The best way to learn: learning by teaching! He had to keep learning things because he needed to explain them. And by explaining he remembered it even better. But one thing kept worrying him: he couldn't pass many of the standard programming interview questions like "validate this binary search algorithm"... The solution could be online courses on coursera, edx, udacity, udemy. What he recommends is https://github.com/ossu/computer-science, an overview of free courses you need to do to theoretically pass a full computer science … -
PyUtrecht: The Earley Lark parses more: from structured text to data classes - Dan Jones
(One of my summaries of the Dutch PyUtrecht meetup in Utrecht, NL). Take your average "advent of code" text parsing problem. First try: some basic string.split() stuff. Not very readable and a bit brittle. Second try: a feast of regex'es.... More elegant, but much less readable. A regex can parse regular text. If text isn't regular, you have to get to "EBNF", extended Backus-Naur form. This is what lark can help you parse. In lark you define a grammar. You can import pre-defined parts of vocabulary like "signed number" or "quoted string". You can define custom types/variables. And you can group stuff. So first some number of "account statements", followed by "whitespace", followed by "transaction statements", for instance. After parsing with lark, you can then process the results. A useful thing you can do is to convert everything to python dataclasses. When you pair it with pydantic, you get even easier type coercion and validation. A nice quote by Miriam Forner: writing code is communicatng to your future self and other developers. So: readability matters. And Lark can help. -
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. -
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. -
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. …