Skip to content

Conversation

ryancheley
Copy link
Contributor

Trac ticket number

ticket-27106

Branch description

Updated the Docs to include examples of how to use template filters in Python code

Checklist

  • This PR targets the main branch.
  • The commit message is written in past tense, mentions the ticket number, and ends with a period.
  • I have checked the "Has patch" ticket flag in the Trac system.
  • I have added or updated relevant tests.
  • I have added or updated relevant docs, including release notes if applicable.
  • I have attached screenshots in both light and dark modes for any UI changes.

… code

Updated the Docs to include examples of how to use template filters in
Python code
@ryancheley
Copy link
Contributor Author

@bmispelon I cleaned up the PR so that it only has a single file in the commit. Thanks!

Copy link
Member

@cliff688 cliff688 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some small notes (partial review)

@ryancheley
Copy link
Contributor Author

@bmispelon I think this is ready for review. When you have a moment can you take a look and let me know what you think?

Co-authored-by: Clifford Gama <53076065+cliff688@users.noreply.github.com>
Copy link
Member

@cliff688 cliff688 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work here. I'd like to reiterate my preference for avoiding the repetition of examples for each filter. I suggest we instead append a single sentence at the end of relevant filter descriptions, e.g.:

When used in Python code as a function, this filter exhibits the same behaviour.

I understand the ticket calls for documenting where to import the filters from and how to use them, but in most cases:

  • The import path is the same: django.template.defaultfilters
  • The usage pattern is also consistent: positional arguments passed to a function

So unless there are special cases (e.g. date, where locale or object type handling introduces nuance), we can likely avoid per-filter examples in favour of one general section near the top of the file.

Perhaps we can introduce something like the following:

diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
index 6ae8250335..cbee9ed7e8 100644
--- a/docs/ref/templates/builtins.txt
+++ b/docs/ref/templates/builtins.txt
@@ -14,6 +14,25 @@ documentation for any custom tags or filters installed.
 Built-in tag reference
 ======================
 
+.. _using-filters-in-python-code::
+
+Using filters in Python code
+----------------------------
+
+Most filters documented here can also be used in Python code. To do so,
+import the desired filter from ``django.template.defaultfilters`` and call
+it like a regular Python function.
+
+For example::
+
+    from django.template.defaultfilters import add
+
+    result = add(4, 2)
+    # result is 6
+
+Unless otherwise noted, filters will behave the same in Python as they do
+in templates.
+
 .. templatetag:: autoescape
 
 ``autoescape``

so that when documenting individual filters, we could simply include a note like:

This filter is also available in Python code. See :ref:`using-filters-in-python-code`.

This approach avoids boilerplate repetition while still meeting the goals of the ticket. I'd be happy to hear if there are reasons to prefer the per-filter examples instead, but this seems like a cleaner and more maintainable option.

@ryancheley
Copy link
Contributor Author

@cliff688 I’d be ok with implementing your suggestion but I’d also want to get @bmispelon perspective as well before making any changes to what’s been done.

Copy link
Contributor

@sarahboyce sarahboyce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your work here @ryanchausse

Based off the discussion in the ticket, the main thing that concerns me is the following:

While I think I've imported from django.template.defaultfilters in some of my own projects, I'm not sure that promoting that pattern as a public API is a good idea. Some of the filters use functions from django.utils.*, e.g. the slugify filter uses django.utils.text.slugify. I don't mind linking to those utility functions from the template tag documentation.

"Why not?" you might ask.
The main concern I would have is potential security considerations. The Django template language is designed to handle data that would be displayed in a template. Encouraging the use outside the template context means that we would imply that this is secure (see https://docs.djangoproject.com/en/5.2/internals/security/#content-displayed-by-the-django-template-language-must-be-under-100-kb). In reality, we have quite strict expectations on how much data gets processed in a template

This is why I see that the ticket was accepted in order to have better links between the template tags and associated utility functions these may be a wrapper of. For example, the filter escape is a wrapper of django.utils.html.conditional_escape but that link is not explicit in the escape docs

I think to resolve this ticket, we want to make sure that filters which already have a public Python API, via the utility function they wrap, are pointed out in the docs
Other filters applying basic python functionality in a template level (such as add) are not necessary. Other filters which don't have a public API for the underlying utility may not want this to be public because of potential security concerns

Does that make sense?

Comment on lines +962 to +963
.. versionadded:: 5.1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.. versionadded:: 5.1

@ryancheley
Copy link
Contributor Author

@sarahboyce your feedback makes a lot of sense to me and I'll work to implement those changes over the coming weeks. Also, I think you may have tagged the wrong Ryan in your comment 😄

@ryanchausse
Copy link
Contributor

Hi @ryancheley and @sarahboyce and @cliff688

Just wanted to say you’re carrying on great work in the Django project.

Happy to see the respectful and thoughtful discussion. Let me know if you’re ever in Melbourne.

Keep on truckin’.

@sarahboyce
Copy link
Contributor

Sorry for the wrong ping! 🤦‍♀️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants