Django Template: Dynamic template variable inside another variable - django

I hope this makes sense... I am building a crypto asset list page (easy); however, in the {% for %} loop I would like to include a variable inside a variable. Showing the code will make more sense:
Tempalte.html
{% for crypto_asset in objects__list_cryptoAssets %}
<tr role="row" class="body-row">
<td role="cell">{{ api_external_prices.bitcoin.usd }}</td>
</tr>
{% endfor %}
So the {% for %} loop grabs all the crypto assets and then I can use Django template {{ asset_class.slug }} to grab all slugs... nothing exceptional here. This variable {{ api_external_prices.bitcoin.usd }} grabs external USD prices for Bitcoin, {{ api_external_prices.bitcoin.eur }} prices in EUR, and so forth... nothing exceptional here either.
Here is where the question comes :: the idea would be to have something like {{ api_external_prices.{{ asset_class.slug }}.usd }}... so each crypto would have its own price FX fetched correctly. Is it possible to have a variable inside a variable?

They are several ways you can implement this:
Template filters
You can create a template filter api_external_prices that takes asset_class and the crypto type as parameters and returns the value.
The syntax would be something link this, where api_external_prices is the name of the template filter:
{{ asset_class|api_external_prices:"usd" }}
See here for more info about this feature: https://docs.djangoproject.com/en/4.0/howto/custom-template-tags/#writing-custom-template-filters
Methods
Another approach would be to have api_external_prices as method on your asset_class object, which returns an object that has a usd property. api_external_prices here can just be a wrapper that calls a central module/function, but this would make it much easier to use it in templates.
{{ asset_class.api_external_prices.usd }}
The first approach is similar to what you are asking, but personally I would prefer to use the 2nd approach, because it saves you from introducing as template filter.

Related

Django custom template filter feeding cookie or default value

I'm designing a custom django filter, just to make sure it works I have something like this
{{ "Sleeps:"|translate:"fr" }}
and it works.
Now in the final implementation, I want it to get a cookie or else use a default value
{{ pg.title|translate:request.COOKIES.lang|default:"en" }}
I'm getting this error
VariableDoesNotExist at /chalet/belle-chery
Failed lookup for key [lang] in {'_ga': 'GA1.1.1026479868.1547798010', 'cookie-policy': 'true', 'csrftoken': 'VrVrvgZUfFrWhFDFjLIvZgOus9NrmjDx1JwNP2lzvz2FRAGmC1lLrKwiH4g31X5F', 'sessionid': 'ptp6smvt9w95qtqlkc7klx736u5k7uu5'}
so it doesn't implement the default part.
So I figure there's either a way to fix this or use middleware to set the cookie if it's not set.
Would be nice if it doesn't need middleware.
so it doesn't implement the default part.
It does, it applies the |default:"en" filter to the result of {{ pg.title|translate:request.COOKIES.lang }}, not to the request.COOKIES.lang expression.
The easiest way to solve this is probably defining a local variable, for example with the {% with ... %} template tag:
{% with lang=request.COOKIES.lang|default:"en" %}
{{ pg.title|translate:lang }}
{% endwith %}

what is difference between {{}} and {% %} in django templates

I am very new to django and working on it.. I visited a html file and dont know the difference between {{}} and {% %} in html files used
as here
{% load static %}
Thanks a lot
You can use
{% %} For sentences such as if and for or to call tags such as load, static, etc.
{{ }} To render variables in the template.
Read More about it at Django Docs
{% %} is for displaying code and {{}} is for displaying variables
There are three things in the template in Django
First is template variable and the second thing is template tag and third and last is template filter
so we write a template variable is {{}}
and write a template tag is {% %}
third and last is template filter {{variable |filter:arg}}
I'm new too for Django, so if i'm wrong, please someone correct me.
The difference between they are:
{{variable}} is used to use a variables. When the template encounters a variable, it evaluates that variable and replaces it with the result.
You also can use filters {{variable|filter}} like this:
{{name|length}} in this case you will use a variable "name" and return the length of that variable.
{%tag%} could use for loops or logic, or load external information into the template to be used by later variables. You can create block tags to help extend other html files parts. Also you can create custom tags.
A good place to see how to do it:
https://www.codementor.io/hiteshgarg14/creating-custom-template-tags-in-django-application-58wvmqm5f
Tags like loops and block, need to be closed.
{% %} for IF ELSE CONDITIONS and FOR LOOP etc
{{ }} for veriables that rendered from view function also used in FOR LOOP veriables like
`enter code here`
{% for obj in qs%}
{{ obj.veriable_name }}
{% endfor %}

how to stop django template code from escaping

Is there any way to completely turn off django auto_escaping when rendering a template within the view code (for an email for example):
from django.template import Context, Template
subject_template_string = "Hi {{ customer.name }}"
subject_template = Template(subject)
context = Context({'customer':MyCustomerModel.objects.get(pk=1)})
subject = subject_template.render(context)
If customer.name is something like "Jack & Jill" - the subject looks like "Hi Jack &\amp; Jill" (without the backslash!)
is there something like
subject = subject_template.render(context, autoescape=False)
edit: The actual templates are created by the client in the database, I'm hoping to avoid having to say add |safe to all templates where this might happen...
Disabling it globally is usually a bad idea since you can easily forget it. I would recommend using the templatetag to disable it for that portion of your template instead.
Something like this:
{% autoescape off %}
This will not be auto-escaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}
How about using mark_safe:
Explicitly mark a string as safe for (HTML) output purposes. The
returned object can be used everywhere a string or unicode object is
appropriate.
It marks a string as safe, so, you should take customer.name out and pass to the template:
from django.utils.safestring import mark_safe
customer = MyCustomerModel.objects.get(pk=1)
context = Context({'customer_name': mark_safe(customer.name)})
subject = subject_template.render(context)
Though, control what is safe or not is better to do inside the template itself, that's why using autoescape should be preffered.
Use Django's autoescape tag:
{% autoescape off %}
{{ body }}
{% endautoescape %}
for more info, check out the docs here.
This is untested, but based on source code review it looks like the context object can take autoescape as a key.
context = Context({'customer':MyCustomerModel.objects.get(pk=1), 'autoescape': False})
subject = subject_template.render(context)
That said, that's a pretty sweeping change. If you know what values the templates might be looking for, it's probably better to use mark_safe on those values and pass in the predefined options. That would have the added benefit of not risking the possibility of the client template calling a method with side effects on the customer. The first time someone writes a template and puts in {{ customer.delete }}, you have a problem.
Just came back to answer my own question with a simple solution, and there were already 4 answers.. thanks.
This is what I've gone with:
subject_template = Template(u'{%% autoescape off %%}%s{%% endautoescape %%}' % email.subject)

Django: How do I get the number of elements returned in a database call?

This seems to me like a very simple question, but I can't seem to find the answer.
All I need to do is determine the number of objects returned by a database query.
The specific circumstance is this: I have a model named Student. This model has a ManyToManyField member named courses_current, which relates to a table of Course models. When I pass my Student instance to a template, I want to be able to do something like the following (the syntax may not be exact, but you'll get the basic idea):
<div id="classes">
{% if student.classes_current.all.size == 0 %}
<h1> HEY! YOU AREN'T TAKING ANY CLASSES! REGISTER NOW!
{% else %}
Here are your courses:
<!-- ... -->
{% endif %}
</div>
Now, I'm fairly certain that X_set.all.size is not a real thing. In the manage.py shell I can just use len(student.classes_current.all()), but I don't know of any way to use built-in functions, and "dictionary-like objects" don't have .size() functions, so I'm at a loss. I'm sure there's a very simple solution (or at least I hope there is), but I can't seem to find it.
{{ student.classes_current.all.count }} but be warned that it doesn't fetch the objects so you will need to do a separate query if you want to loop over them.
If you need loop over the classes for tag has way to get what you need.
{% for cl in student.current_classes.all %}
{{ cl }}
{% empty %}
<h1>Hey! ...</h1>
{% endfor %}
Documentation https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#for-empty

Django Custom Template Tag with Context Variable Argument

I have a custom template tag which shows a calendar. I want to populate certain items on the calendar based on a dynamic value.
Here's the tag:
#register.inclusion_tag("website/_calendar.html")
def calendar_table(post):
post=int(post)
imp=IMP.objects.filter(post__pk=post)
if imp:
...do stuff
In my template, it works fine when I pass a hard coded value, such as
{% load inclusion_tags %}
{% calendar_table "6" %}
However when I try something like {% calendar_table "{{post.id}}" %} , it raises a error a ValueError for the int() attempt. How can I get around this?
You want {% calendar_table post.id %}; the extra {{ and }} are what are causing you the heartburn.
Note that, in your custom tag, you need to take the string ("post.id") that gets passed and resolve it against the context using Variable.resolve. There's more information on that in the Django docs; in particular, look here: http://docs.djangoproject.com/en/1.3/howto/custom-template-tags/#passing-template-variables-to-the-tag