Is there an available method to take a django template and see which objects it needs in the context to render without errors? Alternatively, is it possible to find out programatically, after rendering a template, if any bad template variables were present?
My goal is as follows. Imagine I have a template:
Hello {{ name }}.
Your lucky number is {{lucky_number}}
I would either like a list containing 'name' and 'lucky_number'. Alternatively, if I render that template and provide a context with just 'name', I would like to know that 'lucky_number' was not provided.
I found this which can help me build my alternate solution:
http://excess.org/article/2012/04/paranoid-django-templates/
Related
I want to achieve something like this within a Django template.
{{ variable.function(parameter) }}
Where variable is a variable passed through a context to a template, in this case, an instance of a model.
I have tried different methods, but no one seems to work.
This is not possible in Django templates: they are crippled on purpose in order to prevent template designers from shooting themselves in the foot. The reasoning is that the only logic in templates should be presentation logic and all business logic should be kept in the view. Some people thinks it is fair enough and some think it is a bit condescending (those dumb template designers are not smart enough to use functions and methods safely).
I can think of 3 choices:
use jinja2 instead.
write a custom template filter.
keep all the logic in the view where Django designers think you are supposed to keep it.
I will not explain how to use Jinja2 because it is already explained in the docs and because the example in the question works verbatim if you switch to it instead of native Django templates. This simply works in Jinja2:
{{ variable.function(parameter) }}
Now the template filter solution: first you must follow a code layout convention. The filter itself would be something like this:
# at your_tag_library.py
#register.filter(name='call_with')
def apply_callable(callable, arg):
return callable(arg)
Then in the template you can do:
{% load your_tag_library %}
{{ variable.function|call_with:parameter }}
Of course the last option is the one from Daniel's answer - precompute the value in the view and just display the result in the template:
context['result'] = variable.function(parameter)
And in your template you just need {{ result }}.
There is no way to do this.
You can create another variable and pass it through the context so you could use it.
Like:
context['result'] = variable.function(parameter)
In your view.
And in your template:
{{ result }}
If anyone here is ASP.NET pro, you might know what I mean by user control. I wish to create a similar one in django instead.
So, my problem is that I have several pages in my website, but I need a search bar to appear in every pages. Since I require the views.py to operate this search bar, I cannot do a simple method of
{% include 'something.html' %}
Therefore, can anyone suggest how can I do it?
There are a couple of ways to accomplish what you're wanting to do:
Context Processors
Template Tags
Context Processors can augment the template context with values, regardless of which template is loaded. They are akin to filters in Rails.
Template Tags, like Context Processors, can accomplish anything you can do in Python, but are implemented at the template level.
If you need something to be present on every template, one of the simplest ways to accomplish this is with an inclusion tag, which can also accept values passed to it. An inclusion tag could be implemented at your highest level template, a.k.a your MasterPage, and as long as you don't put it in a block and override it, it would appear on every page that includes that template in its inheritance chain.
If it's just something you want to include on every page, and it doesn't need to do any processing, you should just be able to place the code you want in the top-most template and have subsequent templates inherit that.
I typically have a "base.html" template that all of my templates inherit from. If I need something to be in every page, I put it there. If it's something I want there by default, but want to be able to augment it in subsequent templates, I will place it into a block. That block will let you include or override its default content.
I know this post is kind of old but I just came across it and found a kind-of-solution that works. I call it kind-of-solution because it is a workaround.
I have a few different sites on which I want to display logging information. This display always looks the same (it has the same html) and has the same database table and model class behind it.
My solution/workaround uses the django filters:
in views.py I put the list of log-entries in the context
context = {'list_log': Log.objects.filter(condition = True) }
template = loader.get_template('my_html_file.html')
return HttpResponse(template.render(context, request))
in my_html_file.html I use a custom filter
{{ list_log|get_log_uc|safe }}
in the filters.py I load another html file with this custom filter
#register.filter
def get_log_uc(list_log):
template = loader.get_template('user_control_log.html')
context = { 'list_log' : log }
return template.render(context)
in user_control_log.html I have the user control equivalent html
{% for log in list_log %}
<p>log.something</p>
{% endfor %
Is there a function that returns a list of fields that are expected in template? For example, I have the following template:
hello i am {{ name }}. {% for i in docs %} i have doc {{ i }}
Written in file. And i want to get a dict which contains:
{'name': 'str', 'docs': 'list'}
Is there something like that or i have to write it by myself?
As far as i know, NO....
Your template contains some html and some place holders (and may be something else). What render_to_template doing is, it gets a context dictionary which contain some keys and some data attached to that keys and a template. Then it places the values to those place holders according to their key names, execute some loops or condition checks if your template contains control flows like {% if...%} or {%for....%}
If TEMPLATE_DEBUG is closed in your settings, and if there is a place holder with no matching key in your context dictionary, then it will skip that without raising any error.
Also, if you pass a form object to your template and place your object directly to template as it is (without calling each field separately) [ex: {{form}} or {{form.as_p}} then django will check for fields on the form and palce them as it is shown here. In a such situation, you will only know that form is used. You have to check which fields are used from your Form definition.
If you look through that process, you must know what you need to place your context dictionary. You may write a parser to parse your template but it is far more difficult than just examining the template and find missing data, i guess.
The builtin {% debug %} tag may be helpful for you, however I don't know if I fully understand what you are asking. Basically, if you put the debug tag in your template it will print a lot of useful stuff, including all the variables available in your template.
Perhaps you could take a look at the source code for the debug tag (because they have access to all the variables there), and build a custom tag tag based off of this. Taking a glance at the source, this seems like it would be really simple to do.
I am using .mo files for localization in Django.
Also, in my database, I store some translated text in different fields, such as:
name_en, name_es, name_de (they are all columns in each row).
What will be the best method to choose the correct field inside a template?
i.e.:
{{ name.some_method }} will generate the correct translation based on the current localization.
Thanks,
Meit
You should look at http://goodcode.io/articles/django-multilanguage/ Here’s a simple solution that may fit your use case and is easy to implement and understand.
You should look at Django Transmeta, it work the same way as what you've done (DB fields with language code) but it's a more complete solution. It already deal with the template stuff, etc.
You can check Model Internationalization and Django Packages for more info and ideas in this domain.
I can see two method for doing this, one in your view and the other one is in the template...
In view:
Probably you keep the user language information somewhere so,
user_lang = 'es'
obj = Somemodel.objects.get(pk=123434)
obj.local_name = getattr(obj, 'name_%s'%user_lang)
So, you keep local translation in a specific variable of the instance and in your template you can use is as:
{{obj.local_name}}
But that might be costly if you wish to pass the template a queryset instead of a single instance. For a such usege you have to evaluate that value for each object in your queryset.
In template:
That is a more complex way of solving the porblem in the template...
Define a template tag and pass object_id, and local language information and get the translated text using a similar getattr function. But in that point, if you wish to use this for more than one model, you probably have to pass a content type information for your template tag too, such as:
{% get_translation <object_id> <content_type_id> <local_language> %}
And in your template tag function, do something like:
from django.contrib.contenttypes.models import ContentType
....
cont_obj = Content_type.objects.get_for_id(<cotent_type_id>) #get the related model
obj = cont_obj.get_object_for_this_type(pk=<object_id>) # get your object
return getattr(obj, 'name_%s'%<local_language>)
There are a number of off-the-shelf Django packages that offer template tags, and I'd like to use them in my project despite the fact that it uses Jinja2.
I've seen some workarounds that allow other template engines to use Django tags. These involve creating a mini-template in a string, and passing it to the Django template processor along with the current context. Here are two example of what I'm talking about: Mako templates using Django template tags and Jinja2 templates using Django template tags.
I'm wondering if there's a less hackish solution.
what about moving problem to python's scope
and importing one python's function into another, this way:
in your_jinja_templatetags.py
from some_django_templatetags import somefilter as base_somefilter
#library.filter
def somefilter(value):
return base_somefilter(value)
Unfortunately Django template tags are not directly translatable to Jinja.
Django Template tags can do many different things, and are usually implemented as functions. Fortunately, Jinja can register these functions as globals and call them. This works for "simple" template tags out of the box.
If you are using the official Django Jinja2 backend, see https://docs.djangoproject.com/en/4.1/topics/templates/#django.template.backends.jinja2.Jinja2 to find out how to register a function (in this case your template tag) as a global. Once this is done, you can call the function from within your template as {{ your_tag_function() }}. Remember to pass whatever arguments the template tag function needs!
I like to use the https://github.com/niwinz/django-jinja backend, myself- if you are using this backend, see https://niwi.nz/django-jinja/latest/#_custom_filters_globals_constants_and_tests for how to register a function as a global.
Unfortunately, this only works for "simple" tags out of the box. Some tags are "inclusion tags" or otherwise depend on the Django Template Engine. Since Django Templates can't be rendered within the Jinja engine, you have to do a bit more work to translate these types of tags. You will need to look at the source code to tell the difference and see what they are doing.
What I usually do for the more complicated tags is create a "jinja_functions.py" script in my Django app, then in that script I import the original template tag. Then I write a function that wraps it- calling the original function, getting back usually a dictionary, and then using that dict to render a string which is returned... most tags are simple enough I just use an f string or .format to format them with the results of the dict.
Then I register my new wrapper function as a jinja global and use it in my jinja templates!
The following is an example of where I re-implemented the template tags provided by https://github.com/timonweb/django-tailwind for use with jinja. I combined both the tailwind_css and tailwinf_preload_css tags into a single function, tailwind_css, which I register with Jinja as a global as per the instructions above, then I can call that function as {{ tailwind_css(prefetch=True) }} or {{ tailwind_css() }} within my templates.
from django.templatetags.static import static
from tailwind import get_config
from tailwind.utils import is_path_absolute
def tailwind_css(v=None, prefetch=False):
tailwind_css_path = get_config("TAILWIND_CSS_PATH")
if not is_path_absolute(tailwind_css_path):
tailwind_css_path = static(tailwind_css_path)
if v:
tailwind_css_path = f"{tailwind_css_path}?v={v}"
if prefetch:
rel = 'rel="preload"'
as_str = ' as="style"'
else:
rel = 'rel="stylesheet"'
as_str = ""
return f'<link {rel} href="{tailwind_css_path}"{as_str}>'
In conclusion it works well out of the box for "simple" tags because you can just register them as global functions in Jinja... but for "include" tags or other tags that rely on the Django Template engine, you will have to write your own function :( But usually its not too much work!