Can we use python related api's on the Django templates? - html

I am new to Django and hence not having thorough knowledge about it. So I am facing a few errors in Django.
Currently I am trying to print the type of a variable from the Django template html file as follows:
<center><h2>The type of feature list report for version {%type(version)%} is<h2></center>
For the above, I am getting the following error:
Invalid block tag on line 9: 'type(version)'. Did you forget to register or load this tag?
So what's going wrong here? How can we use the python related api's (like type(), strip(), get(), etc) from the html template files? I think inside the {% .... %} we can use python related evaluations. Am I right?
Please throw some lights on this .

As said, this is not the philosophy of DTL, but some functions that transform input are implemented as filters.
In addition, you can write your own filters and supporting a "type" filter, would be very simple:
from django import template
from typing import Any
register = template.Library()
def filter_type(value: Any) -> str:
return str(type(value))
register.filter('type', filter_type)
See the documentation for details.
Both Jinja's and DTL's approach are explicit over implicit: instead of blindly supporting any python function with all it's dangers, you have to explicitly allow it or implement it.

Running arbitrary Python code in a Django template is intentionally disabled. Aside from security concerns, the reason is your project's business logic should be separate from your presentation layer. This is part of good application design.
There are three primary ways you can call an operation from a Django template.
Pass in a function and call it.
Use a template filter, either custom or built in.
Use a template tag, either custom or built in.
Pass in a function and call it.
Calling a passed in function from a Django template is standard. However, it has two caveats.
The function must return a value that can is a string or can be coerced to a string. (Otherwise nothing will be printed in the template.)
The function must not have any required arguments.
The most common use case is either a computed value or a getter e.g.
class Page(models.Model):
title = models.CharField()
def get_title(self):
return self.title
<h1>{{ page.get_title }}</h1>
Template filters
See Melvyn's answer for an example of template filters.
Template filters operate on a value. So this is perfect for a Python function like type().
Template Tags
Edited: see Melvyn's comment.
Simple Template tags on the other hand work more like a function. They accept positional and keyword arguments and should again return a value. I won't go into inclusion tags or advanced tag compilation and rendering here, but you can read about it in the Django custom template tag docs.
Here is an example of two template tags I often include in a project in debug.py.
import pprint
from django import template
register = template.Library()
pp = pprint.PrettyPrinter(indent=4, width=120)
#register.simple_tag(takes_context=True)
def print_context(context):
pp.pprint(context)
return ""
#register.simple_tag()
def print_thing(thing):
pp.pprint(thing)
return ""
I can use print_context to print the current context in terminal and print_thing to print something.
{% load debug %}
{% print_context %}
{% print_thing 'print this string' %}
You can create a template tag that will do anything a standard Python function can do. This is because a template tag essentially calls the function you create.
Use the constraints of the Django template system to your advantage to create well designed applications where the business logic is located in the views, models, and helpers, and not in the templates.

You may create a class which includes the type, so you can call the type like: variable.type or you can send the type data from the controller.
If you need to make reactive programming logic at the front end, I'd suggest you use Vue, React or Angular.

Related

Thymeleaf Fragments: How to pass String to Fragment to be used as onchange method

I am having an issue with the relationship between my Thymeleaf content file and fragment file that it uses. From the content file, I am passing many parameters to the fragment that are successfully rendered. However, one parameter that isn't working is a string that I'm passing that is to be used as an onchange method. The error I'm getting is that Method call: theMethod() cannot be found... Here is a simplified snippet of the content file that I'll call content.html:
<div>
<span th:replace="inputs::myInput('idExample', 'theMethod()')"></span>
</div>
And then here is the simplified snippet of the fragment file that I'll call fragment.html:
<span th:fragment="myInput(id, onchange)">
<select th:id="${id}" th:onchange="${__${onchange}__}">
...
...
...
</select>
</span>
Now, theMethod() is defined in a .js file that I have tried including directly as a src in both the content.html and fragment.html files, and it still gives the same error that the method call can't be found. And even if I directly define a theMethod() function in content.html and/or fragment.html, it STILL gives the same error. So I'm thinking maybe the structure of what I have in the th:onchange could be incorrect but not sure. For example maybe the ${__${}__} structure is wrong because I'm not that familiar with the detailed Thymeleaf syntaxes out there.
${__${onchange}__} is trying to run ${theMethod()} as Thymeleaf code -- which is having the Thymeleaf interpreter try to run the java function theMethod().
That being said, if you change it to th:onchange="${onchange}", you probably ran into the error Only variable expressions returning numbers or booleans are allowed in this context, any other datatypes are not trusted in the context of this expression
Thymeleaf really doesn't want you try and build JavaScript expressions and output them in html attributes because of the security vulnerabilities that can happen because of this. They typical way to solve problems like these is to pass function arguments to th:data-* attributes and then have hardcoded JavaScript like this:
<select th:data-id="${id}" th:data-name="${name}" onchange="onChange(this.getAttribute('id'), this.getAttribute('name'))">
That may or may not be directly applicable here -- so there is no easy way to solve your problem without restructuring the way you are handling onChange events.

rendering jinja in custom saltstack module

How to render a jinja template within a custom execution module?
I am trying to write a custom module to update confluence pages automatically. It is designed to be similar to "file.managed" call (only template source, context, and it has to respect pillar data available for given node).
can someone offer an example of pillar/context aware function call for rendering jinja template in custom module?
do the same as saltstack does in their file.managed
example :
if template:
contents = __salt__['file.apply_template_on_contents'](
contents,
template=template,
context=context,
defaults=defaults,
saltenv=__env__)

Switch between 2 or more templates with an action in controllers?

I have a default Phoenix application. This app will have a page_controller
which will load an index.html.eex file.
The app will know to use the view to access templates/page/index.html.eex.
Now say you have created another html page which is identical to index.html.eex in every way except it is in French.
As we do not want to create a whole new Phoenix application which will have all the same code, with the exception being the French translation of the current page/index.html.eex, is there a way to tell
the view or the controller which file needs to be loaded.
Is there a plug which can be placed in the router to alter where render will look for it's templates?
First of all I would suggest you to use Gettext to use labels for French pages.
For example you can all French templates keep in the very same folders (to don't change logic for view), but to name them with suffix eg. "index_fr.html.eex" etc. and then you can write quite simple helper (not necessarily a plug) that will add to all of your templates this suffix.
Still, I would recommend you using Gettext - template's source code is only in place and almost all of the logic Gettext handles for you.
I suggest you pick the #patnowak's answer. Use Gettext, that's the tool made for translation and is powerful enough.
If you still want to do it, remember render/3 in controller calls render/2 functions defined in views, if defined. If not, it runs default rendering function and looks for the template. Read docs for more information.
So for example, this is the controller:
def index(conn, params) do
# defined assigns as you wish
render(conn, "index.html", assigns)
end
Now, define this in the view:
def render("index.html, assigns) do
case assigns[:lang] do
"fr" -> render("index_fr.html", assigns)
_others -> render("index_en.html", assigns)
end
end
You may also write a plug to automatically put :lang into assigns:
def lang_plug(conn, opts) do
conn
|> fetch_query_params()
|> (fn cn -> assign(cn, :lang, cn.query_params[:lang] || "en").()
end
Look Plug.Conn to see docs of fetch_query_params/1 and assign/3, and also other functions to fetch language from other places like headers or body.
You get the idea. In the plug, fill assigns with :lang, fetch them inside your defined render function and act appropriately.
Still, Don't do this. Using Gettext is the proper way.

Disable Jinja template caching for certain filter

We have a custom Jinja filter that we use for creating cache busting URL for our Javascript and CSS resources. We now noticed that in our production environment the final, compiled templates get cached. This results in a problem since our template filter sometimes doesn't create a new URL (i.e. when the template wasn't changed but the Javascript was).
Is there a way to force Jinja to reevaluate a certain filter every time and don't cache the result?
Edit 1: We are using constant inputs (name of the file) to the filter.
After lots of Googling, I finally found the real solution to this. Jinja has a special helper called contextfilter that you can use to decorate your function with to make your filter context-aware (and context-dependent). The Jinja bytecode cache will not cache this computed value, even when a constant is passed as input.
In your filter in Python:
from jinja2 import contextfilter
#contextfilter
def asset_url(context, url):
return some_url_thing(url)
In your template:
<link rel="stylesheet" href="{{ 'styles.css' | asset_url }}" />
There is a way to disable caching of the result of a particular filter: it's by not using a constant input, e.g. by exposing a random source as a global variable.
# Expose to Jinja
from random import random as RANDOM
And in the templates
{{ RANDOM() | eval_this_filter_every_time }}
The caching behaviour of Jinja2 can be configured using the cache_size setting: http://jinja.pocoo.org/docs/api/#jinja2.Environment
However, this only caches the templates itself. As long as the input for a filter is variable the output will be variable too.
So... how are you using the filter? Can you post the part of the template and the filter that is getting cached?
The easiest way to do this is:
On your flask server script do this:
from time import ctime
In your app.route() function,
in the return line add:
time=ctime()
for example:
return render_template('signup', error = error, time = ctime())
In the html reference for your css file(if using jinja2) add:
?{{time}}
at the end of your reference line.
That shoud look like this:
<link rel="stylesheet" href="{{ url_for('static', filename='css/base.css')}}?{{time}}">
Worked pretty good for me and the browser stopped caching.
I hope it helps!
Cheers!
-Nelio

How can I use xxx.scala.html in Play2.0 framework Controller

I am a fresh man, using play2.0 framework. Now I have a trouble to use xxx.scala.html. In Eclipse I added a xxx.scala.html, but I cannot use "xxx.render()" function to render my html.
Now I create a form1.scala.html in view package. I want to render this html in controller like this "return ok(form1.render());". But it cannot. Why I cannot?
I have checked Play-Sample(example: 'form' application). In this application controller class, he used form1.scala.html, form2.scala.html, summary.scala.html and so on defend by himself.It's Ok. But I cannot use like this.
views is a regular Scala/Java package, but when the template compiler runs it adds a 'html' package under that which it places the compiled templates in. So the source app/views/myTemplate.scala.html results in the function views.html.myTemplate
The view templates are functions themselves, not classes or objects, the filename becomes the function name, there is no render() method.
So if you have the file app/views/myTemplate.scala.html you will be able to use it like this:
Ok(views.html.myTemplate())
or
import views.html.myTemplate
Ok(mytemplate())