refactor: raise when template data overwrites variables from context_processors (#1484)

This commit is contained in:
Juro Oravec 2025-11-09 21:23:20 +01:00 committed by GitHub
parent 8b95c28309
commit 40fa9c65b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 1 deletions

View file

@ -6,6 +6,10 @@
- Make django-component's position in Django's `INSTALLED_APPS` more lenient by not calling Django's `URLResolver._populate()` if `URLResolver` hasn't been resolved before ([See thread](https://discord.com/channels/1417824875023700000/1417825089675853906/1437034834118840411)).
#### Refactor
- Components now raise error if template data overwrites variables from `context_processors` ([#1482](https://github.com/django-components/django-components/issues/1482))
## v0.143.0
#### Feat

View file

@ -3569,6 +3569,8 @@ class Component(metaclass=ComponentMeta):
# 2. Prepare component state
######################################
context_processors_data = component.context_processors_data
# Required for compatibility with Django's {% extends %} tag
# See https://github.com/django-components/django-components/pull/859
context.render_context.push( # type: ignore[union-attr]
@ -3653,6 +3655,17 @@ class Component(metaclass=ComponentMeta):
),
)
# Check if template_data doesn't conflict with context_processors_data
# See https://github.com/django-components/django-components/issues/1482
# NOTE: This is done after on_component_data so extensions can modify the data first.
if context_processors_data:
for key in template_data:
if key in context_processors_data:
raise ValueError(
f"Variable '{key}' defined in component '{component_name}' conflicts "
"with the same variable from context processors. Rename the variable in the component."
)
# Cache component's JS and CSS scripts, in case they have been evicted from the cache.
cache_component_js(comp_cls, force=False)
cache_component_css(comp_cls, force=False)
@ -3697,7 +3710,7 @@ class Component(metaclass=ComponentMeta):
with context.update( # type: ignore[union-attr]
{
# Make data from context processors available inside templates
**component.context_processors_data,
**context_processors_data,
# Private context fields
_COMPONENT_CONTEXT_KEY: render_id,
COMPONENT_IS_NESTED_KEY: comp_is_nested,

View file

@ -1,5 +1,6 @@
from typing import Dict, Optional, cast
import pytest
from django.http import HttpRequest
from django.template import Context, RequestContext, Template
from pytest_django.asserts import assertHTMLEqual, assertInHTML
@ -969,6 +970,43 @@ class TestContextProcessors:
assert component.request == request
@djc_test(
# Same as settings in testutils.py, but also sets context_processors
django_settings={
"TEMPLATES": [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
"tests/templates/",
"tests/components/",
],
"OPTIONS": {
"builtins": [
"django_components.templatetags.component_tags",
],
"loaders": [
"django.template.loaders.filesystem.Loader",
"django.template.loaders.app_directories.Loader",
"django_components.template_loader.Loader",
],
"context_processors": [
"django.template.context_processors.request",
],
},
},
],
}
)
def test_raises_on_conflict_with_template_data(self):
class TestComponent(Component):
def get_template_data(self, args, kwargs, slots, context):
return {
"request": "OVERWRITTEN",
}
with pytest.raises(ValueError, match="Variable 'request' defined in component 'TestComponent' conflicts"):
TestComponent.render(request=HttpRequest())
@djc_test
class TestOuterContextProperty: