04 Feb 2025

feedDjango community aggregator: Community blog posts

Built with Django Newsletter - 2025 Week 6

Hey, Happy Thursday!

Why are you getting this: *You signed up to receive this newsletter on Built with Django. I promised to send you the latest projects and jobs on the site as well as any other interesting Django content I encountered during the month. If you don't want to receive this newsletter, feel free to unsubscribe anytime.

News and Updates

Sponsors

This issue is sponsored by SEO Blog Bot. Well, sponsor is a strong word. It is just another project of mine that I wanted to share with you 🙈. Fully free!

If you have a side project and are struggling with finding ideas for blog posts, this will help!

If you want to become a real sponsor, just reply to this email or check out available options here.


Projects


Jobs


From the Community


Top 3 links from last Issue


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!

04 Feb 2025 8:30pm GMT

31 Jan 2025

feedDjango community aggregator: Community blog posts

Django News - 400 DSF Members - Jan 31st 2025

News

PyPI Now Supports Project Archival

Projects on PyPI can now be marked as archived.

pypi.org

Django Software Foundation

400 individual members of the Django Software Foundation

The Django Software Foundation reached 400 individual members.

thib.me

Updates to Django

Today 'Updates to Django' is presented by Abigail Afi Gbadago from Djangonaut Space!

Last week we had 21 pull requests merged into Django by 12 different contributors - including 2 first-time contributors! Congratulations to Gregory Mariani and Igor Scheller for having their first commits merged into Django - welcome on board!🎊

Highlights of the changes made:

Django Newsletter

Wagtail CMS

Our updated Accessibility Conformance Report

Wagtail has released a new Accessibility Conformance Report for version 6.3, showcasing improvements across WCAG 2.2 criteria, detailing compliance in the CMS, documentation, and websites, and inviting feedback for further accessibility enhancements.

wagtail.org

Sponsored Link 1

Hiring Jr. Web Services Engineer

This position is for someone who can bring their python software development experience to support Playdate, Game Publishing, and our Apps! You would be responsible for contributing to and maintaining our growing flock of Flask and Django web applications.

Additionally, Panic hires interns every summer via The Script (https://thescript.org/internship-program/), designed for college students with underrepresented backgrounds entering freshman through senior years.

panic.com

Articles

Database Indexing in Django

Explore the fundamentals of database indexing in Django-covering types, advantages, and practical examples-to help you significantly improve query performance and scalability in your projects.

testdriven.io

An Introduction to Django Views

An overview of Django views, covering function-based vs. class-based approaches, best practices, and practical PyCharm tips for streamlined web development.

jetbrains.com

Django 5.2 simple_block_tag with HTMX

Django 5.2 introduces the new simple_block_tag(), demonstrated here with HTMX to validate and test custom attributes for more robust and maintainable components.

better-simple.com

Avoiding Mocks: Testing LLM Applications with LangChain in Django

A practical method for testing Django-based LLM apps with LangChain uses a custom fake backend to avoid mocks, enabling flexible refactoring and thorough validation of model interactions.

lincolnloop.com

Add headings to HTML landmarks

Use visually hidden headings to make your website easier to navigate.

marijkeluttekes.dev

Rendering form fields as group in Django

A welcome addition in Django 5.0, the concept of field groups makes a lot easier to customize the layout of our Django forms.

valentinog.com

Looking at Django task runners and queues

A look at different ways to combine scheduled and one-off background jobs in Django-comparing django-apscheduler, django-tasks, django-q2, Celery, and cron-to handle tasks like sending email and long-running processes efficiently.

loopwerk.io

Events

PyOhio 2025

PyOhio is a free annual Python community conference based in Ohio this July 26-27, 2025.

pyohio.org

Tutorials

How to Use GraphQL in Django with Elasticsearch

A guide to combining Graphene-Django with Django Elasticsearch DSL to create high-performance GraphQL endpoints, complete with advanced search and filtering via Elasticsearch.

djangotricks.com

Sponsored Link 2

Django & Wagtail Hosting for just $9/month

New year, new site! Finally put those domain names to use and launch that side-project, blog, or personal site in 2025. Lock in this limited time pricing by Feb 28.

codered.cloud

Podcasts

Real Python #236: Simon Willison: Using LLMs for Python Development

Simon talks about his LLM research and explores ways of writing Python code with these rapidly evolving tools.

realpython.com

Django News Jobs

Jr. Web Services Engineer at Panic 🆕 (featured)

Senior Backend Engineer at BactoBio 🆕

Software Engineer I at Spark

Senior Software Engineer at Spark

Engineering Manager at Spark

Front-end developer at cassandra.app

Lead Django Developer at cassandra.app

Développeur(se) back-end en CDI at Brief Media

Django Newsletter

Projects

drf-forms/drf-schema-adapter

Making using Django with frontend libraries and frameworks DRYer.

github.com

nanuxbe/django-classy-doc

django-classy-doc brings Classy Class-Based Views-style docs to your own code.

github.com


This RSS feed is published on https://django-news.com/. You can also subscribe via email.

31 Jan 2025 5:00pm GMT

Finishing Simple Signup - Building SaaS #213

In this episode, I completed the simplified sign up process for my JourneyInbox app. I finished off the final features that add account verification and initial engagement features to make sign up and nice and functional experience.

31 Jan 2025 6:00am GMT

29 Jan 2025

feedDjango community aggregator: Community blog posts

Weeknotes (2025 week 05)

Weeknotes (2025 week 05)

Djangonaut Space

In December I wrote a few paragraphs about my decision to not run for the Django Steering Council, mentioning that I want to contribute in different ways.

I have offered to contribute to Djangonaut Space to do some mentoring. I'm already a bit stressed, but that's normal and to be expected. I'll probably have more to share about that in the close future!

Releases

29 Jan 2025 6:00pm GMT

28 Jan 2025

feedDjango community aggregator: Community blog posts

Thinking About Risk: Sidebar #4: Quantitative Risk Revisited

In part 1 of this series, I briefly covered quantitive risk measuring - assigning a numeric value to risk, like "$3,500", rather than a qualitative label like "medium" - only to quickly recommend against trying it. In this final sidebar, I want to come back to this topic. I'll spend a bit more time explaining what I see as the pros and cons of quantitative risk measurement - why you might or might not want to use numeric values over more simple risk matrixes.

28 Jan 2025 6:00am GMT

27 Jan 2025

feedDjango community aggregator: Community blog posts

Python Leiden (NL) meetup: python in applied mathematics - Tobias Datema

(One of my summaries of the first Python Leiden (NL) meetup in Leiden, NL).

Tobias studied applied mathematics at Delft University.

One of the fields he used python for was graph theory. A graph consists of points ("vertices") connected by lines ("edges"). It is a large field with many real world projects like social networks and logistics. He showed a demo he made with networkx, a python library that makes it real easy to do these kinds of graph calculations.

Graphs need to be shown. He used pyviz for that by converting the networkx graph to the format understood by pyviz.

Another field is machine learning. He did an experiment with a simulated self-driving car. He used a library that handles the basics like "reacting to a closed line on the road" and "measuring the distance to the dashed line on the road". The simulation is shown in a visual form, which makes it funny to look at.

In his study, python was also handy for statistics and numerical analysis.

27 Jan 2025 5:00am GMT

Python Leiden (NL) meetup: fawltydeps - Johan Herland

(One of my summaries of the Python Leiden (NL) meetup in Leiden, NL).

FawltyDeps is a python dependency checker. "Finding undeclared and unused dependencies in your notebooks and projects".

Note by Reinout: since 2009 I'm one of the maintainers of z3c.dependencychecker.... also a python dependency checker :-) So this talk interested me a lot, as I didn't know yet about fawltydeps.

A big problem in science is the "replication crisis". Lots of research cannot actually be reproduced when you try it... Data science is part of this problem. Reproducing your jupyter notebook for instance.

Someone looked at 22k+ jupyter notebooks. Only 70% had declared their dependencies, 46% could actually install the dependencies and only 5% actually could be run. ModuleNotFoundError and ImportError were the number 1 and 3 in the list of exceptions!

What is a dependency? For instance "numpy", if you have a import numpy as np in your file. Numpy isn't in the python standard library, you have to install it first.

You can specify dependencies in setup.py, pyproject.toml, requirements.txt and so. If you import something and don't specify it, it is an "undeclared dependency". When you later on remove an import and don't adjust your requirements.txt, you have an "unused dependency". That's not immediately fatal, but it might take up unnecessary space.

FawltyDeps was started to help with this problem: find undeclared and unused dependencies. It reports them. You can ask for a more detailed report with line numbers where the dependencies were found.

FawltyDeps supports most dependency declaration locations. requirements.txt, setup.py, pyproject, conda, etc. And it works with plain python files, notebooks, most python versions and most OSs. You can configure it on the commandline and in config files. There's even a handy command to add an example config to your pyproject.toml.

Handy: you can add it as a pre-commit hook (https://pre-commit.com). And: there's a ready-made github action for it, including good reporting.

Fawltydeps has to deal with several corner cases:

  • Package names that don't match what you import. import sklearn and the dependency scikit-learn.
  • Or setuptools that provides both setuptools and pkg_resources.
  • For this it looks at various locations for installed packages to help figure out those mappings. It helps if you've installed FawltyDeps in your project's virtualenv.
  • You can add your own custom mappings in your configuration to help FawltyDeps.
  • You can exclude directories.
  • There's a default list of "tool" packages that FawltyDeps doesn't complain about if you include them as dependency without importing them. Ruff, black, isort: those kinds of tools.
  • Django projects can have dependencies that aren't actually imported. You can ignore those in the config to prevent them to be imported.
  • At the moment, extra dependencies (like [test] or [dev] dependencies) are just handled as part of the whole set of dependencies.

27 Jan 2025 5:00am GMT

How to Use GraphQL in Django with Elasticsearch

When you need to use GraphQL with Django, a common practice is to use Graphene-Django, which allows you to query Django models. However, directly querying Django models might be too slow, especially when you have many complex relations. To speed that up, you can add one more layer of abstraction and index your Django models to an Elasticsearch server. In this article, I will show you how to create a GraphQL interface for querying posts from the Elasticsearch server.

Elasticsearch Server

The easiest way to install the Elasticsearch server locally is using EVM - Elasticsearch Version Manager:

$ sudo curl -o /usr/local/bin/evm https://raw.githubusercontent.com/duydo/evm/master/evm
$ sudo chmod +x /usr/local/bin/evm

Then you can install Elasticsearch 7.17.27 (or other version) with EVM, as follows:

$ evm install 7.17.27

By default, the Elasticsearch server will raise a warning if you don't have HTTPS or basic authentication. You can change one setting to turn off those warnings for localhost. To do so, add a line to ~/.evm/elasticsearch-7.17.27/config/elasticsearch.yml:

xpack.security.enabled: false

Now, you can start the server with:

$ evm start

If you need more Elasticsearch versions on the same computer, you can easily install and switch between them.

Python Packages

Install the latest packages of Django Elasticsearch DSL for connecting to Elasticsearch server, and Graphene-Django for GraphQL implementation:

(venv)$ pip install Django
(venv)$ pip install django-elasticsearch-dsl
(venv)$ pip install graphene-django

Django Settings

Add the installed apps to INSTALLED_APPS in the myproject/settings.py. Also, add a few more settings that we will need in this exercise:

INSTALLED_APPS = [
    # Contributed Django apps
    # ...

    # Third-party apps
    "django_elasticsearch_dsl",
    "graphene_django",

    # Local apps
    "posts",
]

PROJECT_NAME = "myproject"
ENVIRONMENT = "dev"

ELASTICSEARCH_DSL = {
    "default": {
        "hosts": "http://localhost:9200",
    }
}

GRAPHENE = {
    "SCHEMA": "elasticsearch_graphql.schema.schema",
}

Models and Administration for the Posts App

Let's create a posts app with two models: Category and Post:

The posts/models.py file will look like this:

from django.db import models


class Category(models.Model):
    title = models.CharField("Title", max_length=255)
    slug = models.SlugField("Slug", max_length=255)

    class Meta:
        verbose_name = "Category"
        verbose_name_plural = "Categories"
        ordering = ["title"]

    def __str__(self):
        return self.title


class Post(models.Model):
    title = models.CharField("Title", max_length=255)
    slug = models.SlugField("Slug", max_length=255)
    content = models.TextField("Content")
    categories = models.ManyToManyField(Category)

    class Meta:
        verbose_name = "Post"
        verbose_name_plural = "Posts"
        ordering = ["title"]

    def __str__(self):
        return self.title

Also let's create administration posts/admin.py to be able to add some entries easily:

from django.contrib import admin
from .models import Category, Post


@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ["title", "slug"]
    prepopulated_fields = {"slug": ["title"]}


@admin.register(Post)
class Post(admin.ModelAdmin):
    list_display = ["title", "slug"]
    list_filter = ["categories"]
    filter_horizontal = ["categories"]
    prepopulated_fields = {"slug": ["title"]}

Create the database schema and the superuser, then run the local development server with the following Django management commands:

(venv)$ python makemigrations
(venv)$ python migrate
(venv)$ python createsuperuser
(venv)$ python runserver

Add some posts and categories in the administration:

http://localhost:8000/admin/

Elasticsearch Documents for the Posts

Let's create PostDocument definition for the Elasticsearch index of the Post model and its categories at posts/documents.py:

import graphene

from django.conf import settings
from django_elasticsearch_dsl import Document
from django_elasticsearch_dsl.registries import registry
from django_elasticsearch_dsl import fields
from .models import Post


@registry.register_document
class PostDocument(Document):
    title = fields.TextField()
    slug = fields.KeywordField()
    content = fields.TextField()
    categories = fields.NestedField(
        properties={
            "title": fields.TextField(),
            "slug": fields.KeywordField(),
        }
    )

    class Index:
        name = f"{settings.PROJECT_NAME}_{settings.ENVIRONMENT}_posts"
        settings = {"number_of_shards": 1, "number_of_replicas": 0}

    class Django:
        model = Post

        ignore_signals = False
        auto_refresh = True
        queryset_pagination = 5000

    def prepare(self, instance):
        data = super().prepare(instance)

        # Prepare categories field
        data["categories"] = [
            {
                "title": category.title,
                "slug": category.slug,
            }
            for category in instance.categories.all()
        ]
        return data

To index the posts on the Elasticsearch server, run the following:

(venv)$ python manage.py search_index --rebuild

Let's see if the entries were indexed and can be retrieved.

At first, run the Django shell:

(venv)$ python manage.py shell

Then try to list out items from the Elasticsearch index:

>>> from posts.documents import PostDocument
>>> for doc in PostDocument.search():
...    print(doc.title)

It will list up to 10 posts (that's the default pagination) from the index:

Creating AI-based Summaries in a Django Website
Creating Open Graph Images in Django for Improved Social Media Sharing
HTTPS for Django Development Environment

GraphQL Types and Queries for the Posts App

Now, create the GraphQL schema posts/schema.py for the categories and posts, as follows:

import operator
from functools import reduce

import graphene
from .documents import PostDocument


class ElasticsearchObjectType(graphene.ObjectType):
    @classmethod
    def from_elasticsearch(cls, elasticsearch_document):
        instance = cls()
        instance.elasticsearch_document = elasticsearch_document
        return instance


class ElasticsearchCategoryType(ElasticsearchObjectType):
    title = graphene.String()
    slug = graphene.String()

    def resolve_title(self, info):
        return self.elasticsearch_document.title

    def resolve_slug(self, info):
        return self.elasticsearch_document.slug


class ElasticsearchPostType(ElasticsearchObjectType):
    title = graphene.String()
    slug = graphene.String()
    content = graphene.String()
    categories = graphene.List(of_type=ElasticsearchCategoryType)

    def resolve_title(self, info):
        return self.elasticsearch_document.title

    def resolve_slug(self, info):
        return self.elasticsearch_document.slug

    def resolve_content(self, info):
        return self.elasticsearch_document.content

    def resolve_categories(self, info):
        return [
            ElasticsearchCategoryType.from_elasticsearch(
                elasticsearch_document=category
            )
            for category in self.elasticsearch_document.categories or []
        ]


class Query(object):
    elasticsearch_posts = graphene.List(
        ElasticsearchPostType,
        limit=graphene.Int(),
        offset=graphene.Int(),
        search=graphene.String(),
        categories=graphene.List(of_type=graphene.String),
    )

    def resolve_elasticsearch_posts(
        self,
        info,
        limit=10,
        offset=0,
        search=None,
        categories=None,
    ):
        from elasticsearch_dsl.search import Q

        search_obj = PostDocument.search()

        queries = []
        if search:
            queries.append(
                Q(
                    "multi_match",
                    query=search,
                    fields=[
                        "title^5",
                        "slug^4",
                        "content^3",
                    ],
                    type="best_fields",
                    tie_breaker=0.3,
                    fuzziness="AUTO",
                    fuzzy_transpositions=True,
                    lenient=True,
                )
            )

        if categories:
            queries.append(
                Q(
                    "nested",
                    path="categories",
                    query=Q("terms", categories__slug=categories),
                )
            )

        if queries:
            # All filters AND-ed
            search_obj = search_obj.query(reduce(operator.iand, queries))

        search_obj = search_obj[offset : offset + limit if limit else None]

        return [
            ElasticsearchPostType.from_elasticsearch(elasticsearch_document=result)
            for result in search_obj.execute()
        ]

Here, we have an ElasticsearchObjectType that provides a custom method from_elasticsearch to initiate GraphQL objects from Elasticsearch instead of Django models.

The query for elasticsearch_posts has two filters: by a search string and by a list of OR-ed category slugs. The search query looks into title, slug, and content fields with different boosting weights and searches for the best match. The fuzziness set to "AUTO" allows mistakes in the search string by two letters.

At the project level, create Graphene Relay - a schema class that uses a Query class inheriting from all the Query classes from all Django apps. The file can be located at myproject/schema.py and have this content:

import graphene
import posts.schema

class Query(posts.schema.Query, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query)

Finally, enable the GraphQL endpoint in the myproject/urls.py:

from django.contrib import admin
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView

urlpatterns = [
    path("graphql/", csrf_exempt(GraphQLView.as_view(graphiql=True))),
    path("admin/", admin.site.urls),
]

Checking the GraphQL Queries

Navigate to http://localhost:8000/graphql/

Graphene-Django comes with a GraphiQL user interface, which, when accessed from a browser, allows the user to query GraphQL and see results in the same window:

GraphiQL user interface

A search query for "AI" with categories "Intermediate" or "Advanced" can look like:

query FilteredPosts {
  elasticsearchPosts(
    search: "AI"
    categories: ["intermediate", "advanced"], 
    limit: 10, 
    offset: 0,
  ) {
    title
    slug
    categories {
      title
      slug
    }
  }
}

It will produce results in JSON just like this:

{
  "data": {
    "elasticsearchPosts": [
      {
        "title": "Creating AI-based Summaries in a Django Website",
        "slug": "creating-ai-based-summaries-in-a-django-website",
        "categories": [
          {
            "title": "Basics",
            "slug": "basics"
          },
          {
            "title": "Django",
            "slug": "django"
          },
          {
            "title": "Gemini",
            "slug": "gemini"
          },
          {
            "title": "Intermediate",
            "slug": "intermediate"
          },
          {
            "title": "Large Language Models",
            "slug": "large-language-models"
          },
          {
            "title": "PyBazaar",
            "slug": "pybazaar"
          },
          {
            "title": "Simplemind",
            "slug": "simplemind"
          }
        ]
      },
      {
        "title": "HTTPS for Django Development Environment",
        "slug": "https-for-django-development-environment",
        "categories": [
          {
            "title": "DevOps",
            "slug": "devops"
          },
          {
            "title": "Development",
            "slug": "development"
          },
          {
            "title": "Django",
            "slug": "django"
          },
          {
            "title": "HTTPS",
            "slug": "https"
          },
          {
            "title": "Intermediate",
            "slug": "intermediate"
          },
          {
            "title": "SSL",
            "slug": "ssl"
          },
          {
            "title": "TLS",
            "slug": "tls"
          }
        ]
      }
    ]
  }
}

Conclusion

Using Elasticsearch with GraphQL is not trivial, but it provides excellent performance, especially for complex data structures. The best way to implement that in Django that I know of is combining Django Elasticsearch DSL and Graphene-Django.


Cover photo Angela Roma

27 Jan 2025 4:40am GMT

25 Jan 2025

feedDjango community aggregator: Community blog posts

Looking at Django task runners and queues

I use django-apscheduler to run a queue of scheduled tasks. Now I also need the ability to run one-off tasks and that turned out to not be so simple.

25 Jan 2025 5:59am GMT

24 Jan 2025

feedDjango community aggregator: Community blog posts

Django News - Django 5.2 alpha 1 release - Jan 24th 2025

News

Django 5.2 alpha 1 released

Django 5.2 alpha 1 is now available. It represents the first stage in the 5.2 release cycle and is an opportunity for you to try out the changes coming in Django 5.2.

djangoproject.com

Hello from the new Steering Council; and a quick temporary voting process change

The Steering Council is officially in action, and we want to give you a heads-up on a change we're making for the short term.

djangoproject.com

Djangonaut Space - New session 2025

Djangonaut Space is holding a fourth session! This session will start on February 17th, 2025. Applications are open until January 29th, 2025, Anywhere on Earth.

djangoproject.com

Tailwind CSS v4.0 - Tailwind CSS

Tailwind CSS v4.0 is out - an all-new version of the framework optimized for performance and flexibility, with a reimagined configuration and customization experience, and taking full advantage of the latest advancements the web offers.

tailwindcss.com

Django Software Foundation

President of the Django Software Foundation

Notes from the Thibaud Colas, the new President of the Django Software Foundation.

thib.me

Updates to Django

Today 'Updates to Django' is presented by Velda Kiara from Djangonaut Space!

Last week we had 26 pull requests merged into Django by 10 different contributors - including 1 first-time contributor! Congratulations to Thibaut Decombe for having their first commits merged into Django - welcome on board 🎊!

Big news! Django 5.2a1 is released! Please test the alpha version, try out the new features, and report any regressions on Trac.

The following enhancements were added to Django 5.2 last week:

Django Newsletter

Wagtail CMS

Results of the 2024 Wagtail headless survey

The results of the 2024 Wagtail headless survey are here! There are plenty of expected results plus a few surprises.

wagtail.org

Sponsored Link 1

Django & Wagtail Hosting for just $9/month

New year, new site! Finally put those domain names to use and launch that side-project, blog, or personal site in 2025. Lock in this limited time pricing by Feb 28.

codered.cloud

Articles

Ideas how to support Tailwind CSS 4.x in django-tailwind-cli

A look at potential updates to align with Tailwind's new CSS-first configuration, simplified theme setup, and other breaking changes, while weighing user-friendly migration strategies versus manual transitions.

andrich.me

Monkeypatching Django

A deep dive into how the nanodjango project leverages monkeypatching and metaclass manipulation to enable full Django functionality within a single-file application, bridging the gap between lightweight prototypes and Django's powerful features.

radiac.net

Django Islands: Part 1 - Side Quests by Bo Lopker

On using SolidJS with Django to build a type-safe frontend that the whole team will love.

blopker.com

Show Django forms inside a modal using HTMX

Learn how to create and edit models using Django forms inside a modal using HTMX

joshkaramuth.com

Exploring Python Requirements

A guide to using the uv tool for managing Python project dependencies, showcasing features like tree views, listing outdated packages, and integrating interactive package selection with tools like wheat to streamline dependency updates.

paultraylor.net

Django admin tip: Adding links to related objects in change forms

This article explores two practical methods for enhancing the Django admin interface by linking related objects directly in change forms, improving navigation and usability.

406.ch

Django Developer Salary Report 2025

An annual report from Foxley Talent on Django developer salaries.

foxleytalent.com

urllib3 in 2024

Highlights from 2024 for the urllib3 team in terms of funding, features, and looking forward.

pradet.me

Tutorials

The definitive guide to using Django with SQLite in production

A comprehensive look at using SQLite for Django projects under real-world traffic, detailing its benefits and potential challenges and deployment strategies.

alldjango.com

Sponsored Link 2

Buff your Monolith

Scout Monitoring delivers performance metrics, detailed traces and query stats for all your app routes with a five-minute setup. Add our Log Management and have everything you need to make your Django app shiny and fast. Get started for free at https://try.scoutapm.com/djangonews

scoutapm.com

Podcasts

Django Chat #174: Beyond Golden Pathways - Teaching Django with Sheena O'Connell

Sheena is a long-time Django developer and teacher currently focused on Prelude Tech, small workshops focused on topics like Django, HTMX, and Git.

djangochat.com

Django News Jobs

Senior Backend Engineer at BactoBio 🆕

Software Engineer I at Spark

Senior Software Engineer at Spark

Engineering Manager at Spark

Front-end developer at cassandra.app

Lead Django Developer at cassandra.app

Développeur(se) back-end en CDI at Brief Media

Django Newsletter

Django Forum

Call for Project Ideas and Prospective Mentors for GSoC 2025

Google Summer of Code (GSoC) rolls around again. Historically this has been a real boon for Django, with successes again this year. We need project ideas and prospective mentors for 2025. Do you have one? Is that you?

djangoproject.com

Projects

Salaah01/django-action-triggers

A Django library for asynchronously triggering actions in response to database changes. It supports integration with webhooks, message brokers (e.g., Kafka, RabbitMQ), and can trigger other processes, including AWS Lambda functions.

github.com

OmenApps/django-templated-email-md

An extension for django-templated-email for creating emails with Markdown.

github.com


This RSS feed is published on https://django-news.com/. You can also subscribe via email.

24 Jan 2025 5:00pm GMT

23 Jan 2025

feedDjango community aggregator: Community blog posts

Strip spaces

When I joined TriOptima back in 2010, a common pattern emerged where names of things were slightly off because of stray whitespaces. Sometimes we had duplicates like "foo", "foo " and " foo" in the database. Sometimes we couldn't find stuff in logs because you searched for "foo was deleted", when actually you had to search for "foo was deleted" (notice the double space!). Sorting was "broken" because " foo" and "foobar" are not next to each other. And more issues that I can't remember…

It was everywhere, causing problems across the entire code base. Each individual issue was easily fixed by cleaning up the data, but it added up to an annoying support burden. My fix at the time was to make a function that took a Django Form instance and returned a new instance with space stripping on all fields. Something like:

form = auto_strip(Form(...))

After I added that to every single Django form in the entire code base that slow and steady trickle of bugs and annoyances just stopped. From seeing a few a month consistently to zero for the next ~9 years. Even better: I never got a complaint about it.

This was fixed in Django 1.9 after some fierce debating back and forth ("will never happen" was uttered). In iommi forms we've had this since the beginning, which turns out to be a few months ahead of when Django took this decision (although it was tri.form and not iommi back then).

Just when you think you're out

Unfortunately the story doesn't end here. I started getting this issue again, and it took me a while to realize it's because of SPA-like pages that uses Pydantic serializers instead of a form library. To solve this I added this base class for my schemas:

class Schema(ninja.Schema):
    @validator('*')
    def strip_spaces(cls, v: Any) -> Any:
        if isinstance(v, str) and '\n' not in v:
            return v.strip(' ')
        return v

The reason I'm not stripping spaces if the text contains a newline is to avoid situations where you have multiline text fields with indented code. Maybe it's just programmers who will care, but we tend to care a lot :P

Modifying data silently and by default like this sounds like a bad idea and I also get a little pit in my stomach when I think about it with that frame of mind, but this specific case seems like all win and no downside from my 14 years of experience doing it.

23 Jan 2025 6:00am GMT

22 Jan 2025

feedDjango community aggregator: Community blog posts

Beyond Golden Pathways - Teaching Django with Sheena O’Connell

Sponsor

This episode was brought to you by Buttondown, the easiest way to start, send, and grow your email newsletter. New customers can save 50% off their first year with Buttondown using the coupon code DJANGO.

22 Jan 2025 6:00pm GMT

17 Jan 2025

feedDjango community aggregator: Community blog posts

Django admin tip: Adding links to related objects in change forms

Django admin tip: Adding links to related objects in change forms

Any issue which came up on the Django Forum and Discord is how to add links to other objects to the Django administration interface. It's something I'm doing often and I want to share the pattern I'm using.

It's definitely not rocket science and there are probably better ways to do it, but this one works well for me.

Method 1: Override the change form template

In one project users can be the editor of exactly one organization. The link between organizations and users is achieved using a Editor model with a ForeignKey(Organization) and a OneToOneField(User).

I wanted to add a link to the organization page at the bottom of the user form. An easy way to achieve this is to add a template at templates/admin/auth/user/change_form.html (or something similar if you're using a custom user model):

{% extends "admin/change_form.html" %}

{% block after_related_objects %}
{{ block.super }}

{% if original.editor %}
<fieldset class="module aligned">
<h2>Organization</h2>
<div class="form-row">
  <a href="{% url 'admin:organizations_organization_change' original.editor.organization.pk %}">{{ original.editor.organization }}</a>
</div>
</fieldset>
{% endif %}

{% endblock after_related_objects %}

The original context variable contains the object being edited. The editor attribute is the reverse accessor for the OneToOneField mentioned above.

Method 2: Add a method to the model admin class returning a HTML blob

A terrible but also nice way is to add a method to the ModelAdmin class which returns the HTML containing the links you want, and adding the name of the method to readonly_fields. This is even mentioned in the official readonly_fields documentation but I discovered this by accident a few years back.

The method name doesn't have to be added anywhere else, not to fields nor do you have to define fieldsets for this to work. Just adding it to readonly_fields appends it to the end of the form, before any eventual inlines you're using.

from django.template.loader import render_to_string
from app import models

@admin.register(models.Class)
class ClassAdmin(admin.ModelAdmin):
    list_display = ["name", "language_code"]
    readonly_fields = ["admin_show_custom_districts"]

    @admin.display(description=_("districts")
    def admin_show_custom_districts(self, obj):
        return render_to_string(
            "admin/admin_show_custom_districts.html",
            {"custom_districts": obj.customdistrict_set.all()},
        )

17 Jan 2025 6:00pm GMT

Django News - Django 5.1.5 security release - Jan 17th 2025

News

Django security releases issued: 5.1.5, 5.0.11, and 4.2.18

Several new security updates. As ever, you should endeavor to be on the latest version of Django for security reasons.

djangoproject.com

Django 5.2 alpha 1 released

Django 5.2 alpha 1 is now available. It represents the first stage in the 5.2 release cycle and is an opportunity for you to try out the changes coming in Django 5.2.

djangoproject.com

Python Insider: Python 3.14.0 alpha 4 is out

Python 3.14 is still in development. This release, 3.14.0a4, is the fourth of seven planned alpha releases.

python.org

Djangonaut Space Session 4 Applications Open!

Djangonaut Space Applications are open now and close on January 29th, 2025 AOE.

djangonaut.space

Django Software Foundation

Hello from the new Steering Council; and a quick temporary voting process change

An update on the voting process to move faster on the smaller things the SC currently has in from of them.

djangoproject.com

Updates to Django

Today 'Updates to Django' is presented by Velda Kiara from Djangonaut Space!

Last week we had 20 pull requests merged into Django by 12 different contributors 🎊!

Highlights of the changes made:

Want to see what Djangonauts have been up to? Check out this PR review session

Django Newsletter

Articles

Testing your Python package releases

On discovering that the release process for the Django Debug Toolbar wasn't as robust as thought.

better-simple.com

Catching memory leaks with your test suite

If you have a good test suite, you may be able use pytest fixtures to identify memory and other resource leaks.

pythonspeed.com

Truncating timedeltas in Django

How to efficiently aggregate event counts over time relative to a post's creation in Django by using database annotations.

jmduke.com

How to check if a Django template has been overridden

A quick way to check if a template has been overridden. Especially useful for Django package authors.

laymonage.com

Speed up CI with uv

Use uv to make linting and testing on GitHub Actions around 1.5 times as fast.

hugovk.dev

Django: render JavaScript import maps in templates

How to integrate JavaScript import maps into Django templates using a custom template tag to generate module import paths dynamically.

adamj.eu

State of the Server 2025

An in-depth review of the author's self-hosted server setup, covering hardware, storage, backup strategies, self-hosted applications, security improvements, and future plans for optimization and privacy enhancements.

theorangeone.net

Sponsored Link 2

Buff your Monolith

Scout Monitoring delivers performance metrics, detailed traces and query stats for all your app routes with a five-minute setup. Add our Log Management and have everything you need to make your Django app shiny and fast. Get started for free at https://try.scoutapm.com/djangonews

scoutapm.com

Django News Jobs

Software Engineer I at Spark 🆕

Senior Software Engineer at Spark 🆕

Engineering Manager at Spark 🆕

Front-end developer at cassandra.app

Lead Django Developer at cassandra.app

Développeur(se) back-end en CDI at Brief Media

Full-stack Python Developer at Scalable Path

Django Newsletter

Projects

torchbox/wagtail-wordpress-import

A package for Wagtail CMS to import WordPress blog content from an XML file into Wagtail.

github.com

miketheman/pytest-max-warnings

A Pytest plugin to exit non-zero exit code when the configured maximum warnings has been exceeded.

github.com


This RSS feed is published on https://django-news.com/. You can also subscribe via email.

17 Jan 2025 5:00pm GMT

Signin Email - Building SaaS #212.1

In this episode, we continued on the sign up workflow simplification. The focus of this stream was on adding the background task that will send the magic link email to allow sign in.

17 Jan 2025 6:00am GMT

Building SaaS with Python and Django #212.2

In this episode, we continued on the sign up workflow simplification. The focus of this stream was on adding the background task that will send the magic link email to allow sign in. This is the second half of the stream because my internet cut out.

17 Jan 2025 6:00am GMT