• What we solve ›
  • Focus areas ›
  • Services
  • Work
  • About
  • Contact
Home Blog Type checking related object managers in Django
Type checking related object managers in Django

Introduction

Types have become an important part of Python development. Django uses a fair bit of magic to achieve its ergonomics. That magic can sometimes make type checking difficult. Installing django-stubs gets you quite far, but there are still situations when some type checkers still need some help.

One of these situations can arise when you use related object managers.

Cannot access member X for type Y

Let’s create some fictional models to illustrate the problem.

class Author(models.Model):
    name = models.TextField(max_length=20)


class Category(models.Model):
    name = models.TextField(max_length=20)


class Article(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    authors = models.ManyToManyField(Author, related_name="articles")

A common way of accessing related objects in Django is through related managers. In the above example that could look something like this:

category = Category.objects.get(pk=1)
print(category.article_set.all())


author = Author.objects.get(pk=1)
print(author.articles.all())

The problem? Both article_set and articles are dynamically added to the instance and the type checker doesn’t know anything about them.

Diagnostics as reported by pyright.

Helping the type checker

We can help the type checker by adding the attributes to the respective models when the type checker is running:

from typing import TYPE_CHECKING

from django.db import models

if TYPE_CHECKING:
    from django.db.models.manager import RelatedManager


class Author(models.Model):
    name = models.TextField(max_length=20)

    if TYPE_CHECKING:
        articles: RelatedManager["Article"]


class Category(models.Model):
    name = models.TextField(max_length=20)

    if TYPE_CHECKING:
        article_set: RelatedManager["Article"]


class Article(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    authors = models.ManyToManyField(Author, related_name="articles")

Now proceed and use related object managers without any type errors!

Author
Gustaf Sjöberg
Published at
January 12, 2024
Category
Django
Share
FB , LinkedIn , X
A mountain range
Find your way
Tell us where you want to go, and we'll explore the best ways to get you there.
Get in touch
Simplify complex
energy operations
General
  • Home
  • Services
  • Work
  • About
  • Contact
  • Blog
What we solve
  • Data collection
  • System integration
  • Energy data
  • Control & operations
  • Forecasting & decision support
  • Applications & visualization
Focus areas
  • District heating & cooling
  • Batteries & flexibility
  • Electricity retail & energy services
  • Water utilities
  • Industry & property
  • Electricity grids
Elsewhere
  • Linkedin
  • Instagram
  • Teamtailor
  • GitHub
  • Codeberg
© Helicon Technologies AB
Privacy Terms of use
  • Home
  • What we solve
    • Data collection
    • System integration
    • Energy data
    • Control & operations
    • Forecasting & decision support
    • Applications & visualization
  • Focus areas
    • District heating & cooling
    • Batteries & flexibility
    • Electricity retail & energy services
    • Water utilities
    • Industry & property
    • Electricity grids
  • Services
  • Work
  • About
  • Blog
Simplify complex
energy operations
Contact us
Privacy Terms of use
Data collection
System integration
Energy data
Control & operations
Forecasting & decision support
Applications & visualization
District heating & cooling
Batteries & flexibility
Electricity retail & energy services
Water utilities
Industry & property
Electricity grids