Skip to content

Commit

Permalink
fail-on-template-vars: improve compatibility with Django behavior
Browse files Browse the repository at this point in the history
With `OneToOneField`, Django raises `Model.DoesNotExist` which is
converted by its template engine to `string_if_invalid`:
https://github.com/django/django/blob/5.0.7/django/template/base.py#L932-L933

It is usually falsy, hence the need for `InvalidVarException.__bool__`
to return `bool(self.origin_value)` to be consistent with Django's
default behavior.

However to trigger `InvalidVarException` behavior and its dreaded
`InvalidVarException.__mod__`, it needs to go through this check:
https://github.com/django/django/blob/5.0.7/django/template/base.py#L716
and thus also needs to be truthy hence the stack inspecting `__bool__`
method to know what to return.
  • Loading branch information
xavfernandez authored and bluetech committed Sep 2, 2024
1 parent 089843c commit d7da5ac
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 0 deletions.
8 changes: 8 additions & 0 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,14 @@ def _get_origin() -> str | None:
return name
return None

def __bool__(self) -> bool:
for frame_info in inspect.stack():
if frame_info.function == "resolve" and frame_info.filename.endswith("base.py"):
# To go through this guard:
# https://github.com/django/django/blob/5.0.7/django/template/base.py#L716
return True
return bool(self.origin_value)

def __mod__(self, var: str) -> str:
origin = self._get_origin()
if origin:
Expand Down
42 changes: 42 additions & 0 deletions tests/test_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,48 @@ def test_for_invalid_template(client):
)


@pytest.mark.django_project(
extra_settings="""
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
"""
)
def test_invalid_template_variable_object_does_not_exists_behaves_like_an_empty_string(
django_pytester: DjangoPytester,
) -> None:
django_pytester.create_app_file(
"<div>{% if object_exists %}This should not appear{% endif %}</div>",
"templates/invalid_template_base.html",
)
django_pytester.create_app_file(
"{% include 'invalid_template_base.html' %}",
"templates/invalid_template.html",
)
django_pytester.create_test_module(
"""
from django.core.exceptions import ObjectDoesNotExist
from django.template.loader import render_to_string
import pytest
def fake_one_to_one_relation_missing():
raise ObjectDoesNotExist()
def test_ignore():
assert render_to_string(
'invalid_template.html',
{"object_exists": fake_one_to_one_relation_missing},
) == "<div></div>"
"""
)

result = django_pytester.runpytest_subprocess("-s", "--fail-on-template-vars")

result.assert_outcomes(passed=1)


@pytest.mark.django_project(
extra_settings="""
TEMPLATE_LOADERS = (
Expand Down

0 comments on commit d7da5ac

Please sign in to comment.