18 Sep 2026

feedDjango community aggregator: Community blog posts

Issue 355: DjangoCon Europe 2027 in Innsbruck and Django Probe

News

Executive Director Search Extended to September 22

You don't need to be a Django or Python expert, or already part of the community, to apply for the DSF's first Executive Director role. Applications now close September 22, anywhere on Earth.

DjangoCon Europe 2027 is heading to Innsbruck, Austria! 🏔️⛷️🚠🇦🇹

Tickets are on sale and the Call for Proposals is open for five days of Django, Python, and community in Innsbruck, February 17 to 21, 2027.


Django Software Foundation

DSF Board monthly meeting, Sept 10, 2026

The board approved DEP 0019, discussed next steps in their Executive Director search, committed to funding Djangonaut Space for the next three years, later launched a new corporate sponsorship page, and more.


Python Software Foundation

Announcing the 2026 PSF Board Election Results!

Elaine Wong, Laís Carvalho, Ee Durbin, and Georgi Ker take the four open board seats out of 670 ballots cast, as Cheuk Ting Ho, Chris Neugebauer, and Denny Perez finish their terms.

Announcing the 2026 Python Packaging Council Election Results!

The first Python Packaging Council is seated: Brett Cannon and Pradyun Gedam on two-year terms, Donald Stufft, Henry Schreiner, and Ralf Gommers on one-year terms, so roughly half the council turns over each year.

Announcing the PSF Strategic Plan 2026

Feedback on the June draft reshaped the PSF's five-year plan, which now adds security baseline and vulnerability management objectives, folds translation into accessibility, and clarifies how companies can fund specific work.


Updates to Django

Today, "Updates to Django" is presented by Raffaella from Djangonaut Space! 🚀

Last week we had 9 pull requests merged into Django by 8 different contributors - including 3 first-time contributors! Congratulations to Loïc LEFEVRE, Paul K. Gerke and Rickey Shideler for having their first commits merged into Django - welcome on board!

Thanks to the persistence of the contributors, a great deal of work has been done on the dajngo-admin yes-icons to make it rectangular, which helps people with dichromatic viewing deficiencies.

Kudos for the great work updating the tutorial and cleaning up a section to help newcomers focus on the essentials.


Django Fellow Reports

Django Fellow Report - Natalia

A quieter week, with a mix of security work, reviews, and follow-ups from ongoing work. I spent a good chunk of time on a security report that needed a second triage, including a detailed review of the proposed patch 🔎.

I also wrapped up more of the follow-through from DEP 20 by adapting the release checklists to the new release calendar, and resumed a PR to make EmailValidator more flexible.

And, in particularly happy news 🥳, we welcomed two new members to the Ops Team and two to the Security Team 🎉. I'm thrilled to see both teams growing!

Django Fellow Report - Sarah

This week was quite admin heavy but all positive things! The usual tickets triaged, reviewed, and authored, as well as four security issues, and lots of meetings.

Django Fellow Report - Jacob

An early report for about a day at my desk before heading out for some vacation. Multiple tickets reviewed and authored, along with security/ops/steering council/Fellows meetings.


Sponsored

Simple APM dashboards for Python. Set up in just 5 minutes

Drowning in data? Honeybadger gives you Just Enough APM™ without enterprise bloat or cost.

Our dev-friendly APM dashboards expose metrics and trends across your apps and infrastructure, so you can find and fix Python issues before users notice!


Articles

Django: introducing django-mcpz, for making MCP servers

Because the new MCP version is stateless, a server is just a Django view: route path("mcp", server), decorate functions that take an HttpRequest, and msgspec validates arguments against schemas generated from your type annotations. No ASGI or Channels needed.

Share how you use Django with Django Probe

Tim Schilling wants decisions about what Django adds or deprecates to rest on more than gut feel, so django-probe counts which Django classes, methods, and functions your codebase actually uses and submits the tally. Sign up at djangoprobe.org, then scan and submit.

The Ultimate Question of Architecture, the Universe and Everything

Four projects, one lesson: make being wrong cheap.

Django Management Command for Bulk Import

A walkthrough of writing a custom Django management command to bulk import data.

Django: serve the change password well-known URL

One RedirectView at /.well-known/change-password lets password managers send users straight to your change password page, and Django's default 404s already pass the spec's check for servers that answer 200 to everything.

The PyLadiesCon Portal Was Spammed: 2,249 Fake Accounts. Four Months Before Anyone Noticed

A bot signed up 2,249 accounts on a Django volunteer portal to borrow its sending reputation for email bombing, and at 30 a day nobody noticed until fake accounts were 91% of the database. The fixes: django-simple-captcha, per-IP hourly rate limits, and a scheduled purge of unverified accounts.

Creating Web Widgets Using the Document Picture-in-Picture API

Picture-in-picture isn't just for video: this API floats any HTML in an always-on-top window, and the display-mode: picture-in-picture media query keeps your CSS from breaking once a component leaves the page. Desktop Chrome and Firefox only for now.


Django Forum

Add Plausible Tracking to DjangoProject.com?

Plausible tracking is now live on djangoproject.com and docs.djangoproject.com. This was a long-running discussion over the past 2 years. Thank you to everyone who participated.


Events

Django on the Med - Sept 23rd to 25th

The second Django on the Med development sprints are taking place next week in beautiful Pescara, Italy.

Django Day Copenhagen 2026 - October 2nd

Djangonauts from in and around Denmark are meeting up for the 6th edition of Django Day Copenhagen, to be held on October 2nd. It will be a full day of talks, either to be experienced online -or- at our venue.


Sponsored

Automatic translations on every pull request

New strings in your .po files, translated on-brand before they merge. Localhero runs as a GitHub Action, with a review page where the whole team can tweak the copy. No export, no re-import, no sync step to forget. Rails YAML and JSON too.


Django Job Board

The DSF's search for its first Executive Director, now open through September 22, leads this week's board, alongside a new Django role at The Developer Society, machine learning work at Provision, and a backend seat at The Cruise Brothers.

Executive Director at Django Software Foundation

🆕 Django Developer at The Developer Society

Machine Learning Engineer (Hybrid) at Provision

Django Developer at The Cruise Brothers


Projects

codingjoe/django-letter

Write an email once as a Django template, and django-letter sends it as HTML with inlined CSS plus a plain-text alternative derived from the same markup.

adamchainz/django-mcpz

The package behind the article above, for building MCP servers inside a regular Django project.

18 Sep 2026 3:00pm GMT

17 Sep 2026

feedDjango community aggregator: Community blog posts

September Python Leiden meetup summaries

Two summaries from the September 2026 https://pythonleiden.nl/.

Maintaining Python packages to attract free and open source software contributors - Steve Piercy

Steve is in the Netherlands for next week's Plone conference in Maastricht (NL). He's been involved in open source software for over two decades.

What are contributors? Contributors to open source software? Why do you do it? Learning (I myself got a good programming education out of contributing to Zope/Plone while still at the university). You might want to give back. You might like the community, you like to belong to the community. Finding your tribe. Perhaps build a resume or CV. Help other people.

Why not? Negative online reactions. You want to really make money out of it. AI slop. You might not have time. Too busy. Life happens. You might enjoy walking your dog or doing gardening more. Or perhaps you just don't know how! Or you don't feel experienced enough (imposter syndrome). Perhaps you don't think your English is good enough (he advocates just using Google Translate).

(He asked how many people had already contributed to open source: about half the room raised their hands.)

There are actually lots of ways to contribute. It is not all code! Read this page for some examples. You can report security vulnerabilities or issues. You can comment on issues and help getting them forward. Review pull requests. Extend the documentation. You can join discussions in forums or on Matrix. Write a blog post on a project. And... you can financially sponsor a project.

(He again asked who had contributed: now most hands went up!)

Where to start? Start with what you use and what you find interesting. This helps staying involved and getting into the community more and more. He himself liked web applications and especially forms: making sure they're intuitive and safe and well-validated. And he liked documentation, so some of his first contributions were documentation fixes for open source projects.

Recently, he volunteered to take over maintainership of an open source project (a sphinx extension). There were lots of open pull requests and he asked the owners to look at it again and perhaps tweak it a bit and... everybody responded and a few weeks later he could make a new release with lots of fixes.

What is a maintainer? Well, basically maintainers are contributors who make releases. But ideally you also have to "tend your garden" and try to get your small community to thrive. One thing to keep in mind: you have to put your ego aside. If it is open source, it is really owned by your users, not by you. What do you have to do? Show up when someone has a question. Document your project (how to contribute, how to report bugs and security issues, etc.).

He especially mentioned https://djangonaut.space , that's a great initiative to help people get involved with contributing. Same with https://djangogirls.org/ .

As a maintainer, you might also have to look for funding. There are options like "github sponsors". But also NLnet (from the Netherlands) and the German sovereign tech agency that sponsor lots of projects.

A best practice of good maintainers is to have good tooling. Automatic tests + coverage. Build documentation. Formatting checks. zest.releaser for good releases.

The most important part of being a maintainer: how do you treat people.

There's one big problem: AI. There are just too many pull requests and too many issues. You can never get through them if your project is reasonably project. Dealing with it is hard. Several projects made the choice to disallow AI contributions. Also read https://leidendeclaration.ai/ , for the same problems are entering math and science, too.

But on the other hand... in the icalendar project that he helps maintain, they got a new contributor that made his first contribution based on AI. He liked that: the person got enough confidence through AI. They now have an AI guideline in their contributor guide now.

There's are automated tools on github that can help you check pull requests and identify slop-generating accounts, for instance. A tip when confronted with suspected AI work: ask vague, clarifying questions. Just ask for a bit of clarification in a vague way: AIs can't respond to vague questions, but humans can.

"Once men turned their thinking over to machines in the hope that this would set them free. But that only permitted other men with machines to enslave them." - Frank Herbert, Dune. Funny that he could write that 50 years ago.

Something mentioned in the discussion: people are now bidding on real github accounts in order to let AI bots use accounts that appear real...

Watch out with AI. One of the links he shared: https://pivot-to-ai.com/2026/09/08/students-who-dont-use-ai-are-ahead-on-every-measure/ . And, look at the kids: it was bad enough with social media, but AI is much worse. And freelancers are getting buried with soulless AI slop cleanup: artists get to clean up AI-generated images, for instance.

Choose wisely. A quote he wanted to give us to think about: teach the world you want.

Monitoring my washing machine - Michiel Beijen

Michiel has a 2021 Samsung washing machine that plays Die Forelle by Schubert when it is finished washing... But the washing machine sits in the garage so he can't hear the sound. It is a smart machine, so there's an iphone app for that! "SmartThings". But the list of data it wants to collect about you is horrendeous. And the app is almost 1GB! No...

There's also "home assistant", written in python. There's even a SmartThings API connection. But... from October 2026 onwards you need a $5/month samsung subscription!?!

There's also "Matter". They call it vendor neutral, standards compliant. Samsung supports it. But only for connecting Matter devices to SmartThings, not the other way around.

Next try: put a small camera in front of the washing machine's display, add a bit of OCR text recognition to detect the remaining time from the image and add an http interface to it. An old webcam couldn't provide a good camera. A raspberry Pi Camera 3 did the trick. (He later thought it would perhaps have been better to pick some old smartphone.)

He showed some graphs detailing how the washing machine estimates the time it will finish, including the adjustments it made halfway (adjusting for load or so).

Another approach that a colleague of him took: use a monitoring plug that measures the electricity used. Once the electricity usage drops off, the wash is finished.

17 Sep 2026 4:00am GMT

16 Sep 2026

feedDjango community aggregator: Community blog posts

Django: serve the change password well-known URL

When a password manager detects that a user's password has been leaked or reused, it can prompt them to change it, but the password change URL varies by site. The web's answer to such discovery problems is the reserved /.well-known/ URL namespace (RFC 8615), home to machine-readable files and endpoints like security.txt. A Well-Known URL for Changing Passwords is the web specification that uses this namespace to fix password page discovery. It reserves the URL path /.well-known/change-password to redirect to your actual change password page, wherever that lives.

Password managers that use this URL include Apple's iCloud Keychain (in Safari since 2019), Google Password Manager (since Chrome 86, 2020), and 1Password. web.dev has an excellent article explaining the specification and showing the Google Password Manager feature in action.

In this post, we'll look at implementing the change password URL in a Django project.

Add the redirect

The specification asks that /.well-known/change-password redirect to your change password page with a temporary redirect status code, for which you can use Django's RedirectView. The pattern_name argument looks up the target URL by name, so the redirect stays correct even if you move the page.

So, to add a redirect, plop this path in your root URLconf:

from django.urls import path
from django.views.generic import RedirectView

urlpatterns = [
    # ...
    path(
        ".well-known/change-password",
        RedirectView.as_view(pattern_name="password_change"),
    ),
    # ...
]

Note the path has no trailing slash, per the specification and counter to Django's default pattern. There's also no need for a name= argument, since nothing on your site should link to the URL.

password_change is the URL name provided by django.contrib.auth.urls, which serves Django's built-in PasswordChangeView. This assumes your URLconf includes those URLs, conventionally mounted at accounts/:

path("accounts/", include("django.contrib.auth.urls")),

If you serve your change password page some other way, swap in the appropriate URL name for pattern_name, such as account_change_password if you use django-allauth. Django doesn't check pattern_name until a request arrives, so a wrong name here fails only when the URL is visited, hence the test below.

Check with runserver and visit http://localhost:8000/.well-known/change-password - you should land on your change password page (or the login page redirecting you there with ?next).

Password managers only ever visit the URL on your live site (with HTTPS), so after deploying, repeat the check on your production domain.

For an end-to-end check, Chrome's password checkup tool (under SettingsPasswords) shows a "Change password" button for compromised entries, which should open your page directly once the redirect is deployed. To make the button appear without waiting for a real breach, temporarily change your saved password for the site to a deliberately weak one, like password123, which Chrome flags in the check.

Public users only

By the way, this feature is for public users and their password change pages, not admins. So don't use this feature to redirect to your Django admin's password change view, or any other private page. That would advertise those URLs to the world, undoing the common hardening of hosting Django's admin at a non-default path.

Check the resource that should not exist

There's a second URL to be aware of, a check for whether your server is broken. Some misconfigured servers respond with 200 to every request, serving an error page instead of using a proper 404 status code. On such a server, a client fetching /.well-known/change-password can't tell whether it found a real change password page or an error page.

The specification solves this with a second reserved path, gloriously named:

/.well-known/resource-that-should-not-exist-whose-status-code-should-not-be-200

Clients may request this URL to detect broken servers. If it responds with a 200, the server's status codes are deemed meaningless, so the client ignores the change password URL and falls back to something cruder, like opening your homepage.

Django responds with a 404 for unmatched URLs, so your site should pass this check, with nothing to implement. But a catch-all URL pattern could break it, such as one serving pages from a CMS, or a single-page application fallback that serves index.html with a 200 for any path. So it's worth covering with a test, included below.

Add tests

As ever, it's best to include tests to guard against accidental breakage, such as removal of the URL. Here's a test case covering both URLs:

from http import HTTPStatus

from django.test import SimpleTestCase
from django.urls import resolve


class ChangePasswordWellKnownTests(SimpleTestCase):
    """
    Test the well-known URLs for changing passwords, per:
    https://adamj.eu/tech/2026/09/16/django-change-password-url/
    """

    def test_change_password(self):
        response = self.client.get("/.well-known/change-password")

        self.assertRedirects(
            response,
            "/accounts/password_change/",
            fetch_redirect_response=False,
        )
        resolve(response["Location"])  # Check it's a real URL

    def test_resource_that_should_not_exist(self):
        response = self.client.get(
            "/.well-known/resource-that-should-not-exist-whose-status-code-should-not-be-200"
        )

        self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND)

Notes:

  • Neither view uses the database, so the test case uses SimpleTestCase, which blocks database access and runs a little faster.
  • assertRedirects checks both the status code, 302 by default, and the target URL.
  • The target URL is hardcoded, matching where the auth URLs were mounted earlier. If yours live elsewhere, adjust it. Hardcoding, rather than using reverse(), makes the test check what clients see, rather than using any internal details of your system.
  • Passing fetch_redirect_response=False stops the test client from following the redirect. Without it, assertRedirects would fetch the change password page and fail, because when logged out that page responds with a second redirect, to the login page.
  • resolve() raises Resolver404 if the target URL doesn't map to a view. Calling it makes up for the skipped fetch above, checking that the redirect points at a real page rather than a typo.

Check your form's autocomplete attributes

The web.dev article also recommends annotating your change password form fields with autocomplete attributes, so password managers can fill in the current password and suggest a generated replacement:

  • autocomplete="current-password" on the current password field
  • autocomplete="new-password" on the new password field(s)

If you use Django's built-in PasswordChangeForm, it's done for you, as the widgets there have included these attributes since Django 3.0.

But if you've built a custom form, it's worth checking that its fields carry the right attributes. You can set them through the attrs argument of each field's widget, for example:

from django import forms


class ChangePasswordForm(forms.Form):
    current_password = forms.CharField(
        widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
    )
    new_password = forms.CharField(
        widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
    )
    ...

If you're customizing Django's flow, prefer subclassing PasswordChangeForm, which carries those attributes already.

Fin

So there we go, a nice little standard to make your user's security a little easier. Add one URL entry and password managers can shepherd your users away from compromised passwords.

May your data never leak and your users passwords always be strong,

-Adam

16 Sep 2026 4:00am GMT