Opened 8 months ago

Closed 8 months ago

Last modified 8 months ago

#34878 closed Bug (fixed)

Autoreload crashes with FORM_RENDERER="django.forms.renderers.TemplatesSetting".

Reported by: danjac Owned by: danjac
Component: Template system Version: 5.0
Severity: Release blocker Keywords:
Cc: Priyank Panchal, Jannis Vajen Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description (last modified by danjac)

Running Python 3.11 and Django 5.0a1.

I have the following settings:

DEBUG = True

FORM_RENDERER = "django.forms.renderers.TemplatesSetting"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "OPTIONS": {
            "debug": True,
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.template.context_processors.i18n",
                "django.template.context_processors.media",
                "django.template.context_processors.static",
                "django.template.context_processors.tz",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    }
]

This causes the development server (i.e. manage.py runserver) to crash whenever a template is saved:

  File "python-path/lib/python3.11/site-packages/django/template/autoreload.py", line 60, in template_changed
    reset_loaders()
  File "python-path/lib/python3.11/site-packages/django/template/autoreload.py", line 42, in reset_loaders
    backend = get_default_renderer().engine
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'TemplatesSetting' object has no attribute 'engine'

Change History (10)

comment:1 by danjac, 8 months ago

Description: modified (diff)

comment:2 by Mariusz Felisiak, 8 months ago

Cc: Priyank Panchal added
Severity: NormalRelease blocker
Summary: Setting FORM_RENDERER="django.forms.renderers.TemplatesSetting" causes template autoreload to crashAutoreload crashes with FORM_RENDERER="django.forms.renderers.TemplatesSetting".
Triage Stage: UnreviewedAccepted
Type: UncategorizedBug

Thanks for the report. Would you like to prepare a patch? (a regression test is required, sth similar to the template_tests.test_autoreloader.TemplateReloadTests.test_form_template_reset_template_change_reset_call but with changed FORM_RENDERER).
The following works for me:

  • django/template/autoreload.py

    diff --git a/django/template/autoreload.py b/django/template/autoreload.py
    index 01dd564da4..b727d64168 100644
    a b def reset_loaders():  
    3939        for loader in backend.engine.template_loaders:
    4040            loader.reset()
    4141
    42     backend = get_default_renderer().engine
    43     if isinstance(backend, DjangoTemplates):
    44         for loader in backend.engine.template_loaders:
     42    renderer = get_default_renderer()
     43    if hasattr(renderer, "engine") and isinstance(renderer.engine, DjangoTemplates):
     44        for loader in renderer.engine.engine.template_loaders:
    4545            loader.reset()
    4646
    4747

Regression in 439242c5943e16dd5a3a68fadac76e5e723eb323.

comment:3 by Jannis Vajen, 8 months ago

Cc: Jannis Vajen added

comment:4 by Mariusz Felisiak, 8 months ago

Easy pickings: set

The following could be a regression test:

  • tests/template_tests/test_autoreloader.py

    diff --git a/tests/template_tests/test_autoreloader.py b/tests/template_tests/test_autoreloader.py
    index 4fd7549a70..91ef94406c 100644
    a b  
    11from pathlib import Path
    22from unittest import mock
    33
     4from django.forms.renderers import get_default_renderer
    45from django.template import autoreload
    56from django.test import SimpleTestCase, override_settings
    67from django.test.utils import require_jinja2
    class TemplateReloadTests(SimpleTestCase):  
    6869        self.assertIs(autoreload.template_changed(None, template_path), True)
    6970        mock_loader_reset.assert_called_once()
    7071
     72    @override_settings(FORM_RENDERER="django.forms.renderers.TemplatesSetting")
     73    @mock.patch("django.template.loaders.cached.Loader.reset")
     74    def test_form_template_reset_template_change_no_djangotemplates(
     75        self, mock_loader_reset,
     76    ):
     77        get_default_renderer.cache_clear()
     78        template_path = Path(__file__).parent / "templates" / "index.html"
     79        self.assertIs(autoreload.template_changed(None, template_path), True)
     80        mock_loader_reset.assert_not_called()
     81        get_default_renderer.cache_clear()
     82
    7183    @mock.patch("django.forms.renderers.get_default_renderer")
    7284    def test_form_template_reset_non_template_change(self, mock_renderer):
    7385        self.assertIsNone(autoreload.template_changed(None, Path(__file__)))

comment:5 by danjac, 8 months ago

I've submitted a PR as per suggestions:

https://github.com/django/django/pull/17318

Last edited 8 months ago by danjac (previous) (diff)

comment:6 by danjac, 8 months ago

Has patch: set

comment:7 by Natalia Bidart, 8 months ago

Patch needs improvement: set

comment:8 by Mariusz Felisiak, 8 months ago

Owner: changed from nobody to danjac
Patch needs improvement: unset
Status: newassigned
Triage Stage: AcceptedReady for checkin

comment:9 by Mariusz Felisiak <felisiak.mariusz@…>, 8 months ago

Resolution: fixed
Status: assignedclosed

In fe835c23:

Fixed #34878 -- Fixed autoreloader crash when FORM_RENDERER is set to TemplatesSetting.

Regression in 439242c5943e16dd5a3a68fadac76e5e723eb323.

comment:10 by Mariusz Felisiak <felisiak.mariusz@…>, 8 months ago

In e60fe3b:

[5.0.x] Fixed #34878 -- Fixed autoreloader crash when FORM_RENDERER is set to TemplatesSetting.

Regression in 439242c5943e16dd5a3a68fadac76e5e723eb323.

Backport of fe835c2355072fc2b7a0fbbc57d05477c7ee6ce9 from main

Note: See TracTickets for help on using tickets.
Back to Top