Django templates - Formatting strings - django

I've these variables:
#Int
user.id
#Float (e.g. X.YYYY)
profile.rating
I need these formatted like so (the ` is delimiter):
`profile.rating`
I've tried numerous ways to format them, but none worked. For example, concatenating them: ""|add:profile.rating|add:"" gave me nothing (literally, nothing).
I suspect that this is because add: is numbers-first, but converting the numbers into string with either slugify or stringformat:"" gave me, again, nothing.
How do I do this?
Do note: I need to do this with filters since the result will be passed as a parameter to an include.
Update:
Basically, I'm building a sort of modular include. It include looks like this:
<section>
...
{% if custom_section %}
<section id="{{ custom_section_id }}">
{{ custom_section }}
</section>
{% endif %}
...
</section>
which means that I can't just directly include the values in a parameter, I need the markup that will go inside the nested section.

I managed to solve this issue with this piece of markup:
{% with "<a href="\"/user/" as link_start %}
{% with profile.rating|stringformat:".1f" as rating %}
{% with user.id|slugify as id %}
{% with link_start|add:id|add:"/\">" as link %}
{% with link|add:rating|add:"/5</a>" as data %}
{% include "XX" with custom_data:data|safe %}
{% endwith %} a couple of times
Key here is the |stringformat:".1f" and the user.id|slugify since without them, djangos worthless templating language defaults on the belief all values are numerical, and thus crap comes out.
Of note is the |safe as well, as without it the language escapes the value.

Do note: I need to do this with filters since the result will be
passed as a parameter to an include.
You can pass them directly to include, as it will take context correctly.
{% include user.id %}

Related

Template NoReverseMatch exceptions, outside of Models

I am generating some Django template code on the fly, in order to display rows in tables that are not stored in
a Django database and do not have models. I know the database and I can introspect them if needed, but I don't want
to write code by hand.
For example, field PSOPRDEFN.OPRCLASS stores an optional reference to a particular row where PSCLASSDEFN.OPRID=PSOPRDEFN.OPRCLASS, essentially a foreign key relationship. If there is no relationship PSOPRDEFN.OPRCLASS has one ' ' (space character) in it.
I also have a page for a given PSCLASSDEFN row, where the url is:
url(r'^(?i)permissions/(?P<CLASSID>[A-Z0-9_&]{1,50})/$',
'pssecurity.views.psclassdefn_detail',
name="psclassdefn_detail"),
Note that the ?P CLASSID regular expression does not allow for blanks which corresponds to gets stored in the PSCLASSDEFN table - I figure it's safer to limit what the user can put in the url request.
Back to my generated template: I want to hyperlink to the relation, if it exists. I feed my home-grown template generator a json "directive" indicating what I want put into the template (thanks for the inspiration, django-tables2):
....
{
"colname": "LANGUAGE_CD"
},
{
"urlname": "security:psclassdefn_detail",
"colname": "OPRCLASS",
"kwargs": [
{
"colname": "dbr",
"accessor": "dbr"
},
{
"colname": "CLASSID",
"accessor": "inst.OPRCLASS"
}
]
},
...
Some fairly trivial code generation then results in:
<div class="row">
<div class="col-xs-6 fieldlabel" title="LANGUAGE_CD" >Language Code</div>
<div class="col-xs-6 fieldvalue text-left _fv_LANGUAGE_CD">{{inst.LANGUAGE_CD}}</div>
</div>
<div class="row">
<div class="col-xs-6 fieldlabel" title="OPRCLASS" >Primary Permission List</div>
<div class="col-xs-6 fieldvalue _fv_OPRCLASS">
{% if inst.OPRCLASS|slugify %}
{{inst.OPRCLASS}}
{% endif %}
</div>
</div>
My problem is that started getting random Template url resolution errors when displaying some of the PSOPRDEFN data. I eventually tracked it down to the blank OPRCLASS fields in some rows.
In order to avoid this I first added
{% if inst.OPRCLASS %}
<a ...></a>
{% endif %}
That didn't work because the field is not empty, it is blank (and therefore doesn't match the CLASSID regex). So, this is where I read the filter docs again and found that slugify strips out blanks and non-alpha.
{% if inst.OPRCLASS | slugify %}
<a ...></a>
{% endif %}
Works, as a workaround. The problem is that CLASSID only stores alphanum, but that's not always true for other fields. I wouldn't mind introspecting the table column definition at template generation runtime to see what to do, but I need to find an appropriate way to disable url reversal, for only some rows.
Questions. Is there a better filter, such as a |strip? I suppose I could always build my own filter.
Even better, is there a tag to selectively catch NoReverseMatch' exceptions at template generation time?
{% try NoReverseMatch %}
{{inst.OPRCLASS}}
{% endtry %}
The reason I was so verbose in my description is because this is not something that can be worked around using Models. And neither can I custom-tune the template by hand. I find Django works quite well without models in most cases, but url reversing in templates can be quite brittle when a few rows of data do not match expectations. Hardening it would be very beneficial.
You can assign the result of the url tag to a variable.
{% url 'path.to.view' arg arg2 as the_url %}
{% if the_url %}
link
{% else %}
No link
{% endif %}
This syntax does not raise an exception if reversing the view fails.

Detecting a URL in a Django wizard_form.html template

I have three SurveyWizardViews all of which use the same standard wizard_form.html which is located at templates/formtools/wizard/wizard_form.html as per the documentation
I have added some basic logic to this template which is designed to detect which page of the form the user is on so that I can include a non standard page/step, this is an image with a JS slider bar underneath. This all works perfectly.
{% if wizard.steps.current == '6' %}
<img src="{% static "survey/images/pathtwo/" %}{{display_image}}"/>
<section>
<span class="tooltip"></span>
<div id="slider"></div>
<span class="volume"></span>
</section>
{% endif %}
However I now want to have a slightly different experience for the user depending on which View/URL they are coming from.
Question Is it possible to detect which URL the view is currently using to look at the page? e.g.
{% if URL.current == 'www.mywebsite.com/experiment/surveyone/' %}
do X
{% if URL.current == 'www.mywebsite.com/experiment/surveytwo/' %}
do y
I have done some searching but Im not even sure what I'm searching for to be honest. Any help would be much appreciated.
You can use the request context variable. Something like:
{% if 'experiment/surveyone' in request.path %}
do this
{% endif %}
I prefer using in instead of == to ignore trailing and leading slashes. If you want the whole thing try the build_absolute_uri method. Also check what options does request offer to you (https://docs.djangoproject.com/en/dev/ref/request-response/#httprequest-objects).
Finally, don't forget to add django.core.context_processors.request to your TEMPLATE_CONTEXT_PROCESSORS (I think it is added by default).

Can I specify a multiline context variable/parameter when {% include %}ing a template?

I know that it is possible to set context variables when including a Django template from another template using
{% include "default_table.html" with table_header=table_header1 table_data=table_data1 %}
or
{% with "My data" as table_data %}
{% include 'default_table.html' %}
{% endwith %}
My issue with this is that both approaches don't let me define multiline variables (unless they are based on a previous multiline variable of course).
My specific usecase is this
<!-- widget.html -->
<div class="box">
<div class="title">{{ title }}</div>
<div class="title">{{ body }}</div>
</div>
and I'd like to be able to set a longer text for the body context variable. This will make is possible for me to reuse common widget HTML in various places. Can this be done?
I've been searching a bit on http://djangosnippets.org for an über {% with ... %} template tag, but haven't found any so far.
This Django snippet kinda solves my issue: http://djangosnippets.org/snippets/1860/ But I'd love to be able to set context variables instead of defining {% localblock step_ready_js %}{% endlocalblock %} in my widget HTML.

Indeterminite number of apps/widgets in Django template

I'm working on a site that will have a bunch of pages with an indeterminate amount of "apps" on each page. Something like a calendar app, and a random picture app, or whatever, each in a neat little box. While it's possible to write a template with a bunch of if tags that include other templates, this is a bit of a hassle. I'd like to pass in some variables and have forms on some of these apps, so it would get out of hand quickly. Writing custom inclusion tags will be better than {% include x %}, but it would still be a lot of if statements and writing out every possible app for each page.
Is there any way to loop over something like inclusion tags and include only those that are relevant? Any other completely different solution that I'm missing?
What I'm trying to avoid, whether I use {% include %} or inclusion tags, is this:
{% if apps.calendar %}
{% include "calendar.html" %}
{% endif %}
{% if apps.pictures %}
{% include "pictures.html" %}
{% endif %}
This would mean we'd have to update templates any time a new app was added. What would be nice is something like:
{% for app in apps %}
{% call appropriate include or inclusion tag %}
{% endfor %}
With very few exceptions we use our custom tags all over the place, so we deal with this by simply placing the following in the app/__init__.py file.
from django import template
template.add_to_builtins('content.templatetags.local_tags')
template.add_to_builtins('utils.cachetemplate')
So all of the pages have them available by default. Doesn't seem to impact performance and we use tag names that are unlikely to interfere with other stuff we might include. It's lazy but it works.
Update: OK, I think I better understand what you want. One way of doing this (although I don't really recommend it) is to put the check for the variables inside the included templates. This means you will always have the overhead of including the template, but it will make your other pages marginally less cluttered.
So instead of this in your main file:
{% if apps.calendar %}
{% include "calendar.html" %}
{% endif %}
you simply have:
{% include "calendar.html" %}
and in "calendar.html" you have:
{% if apps.calendar %}
whatever you do for your calendar app
{% endif %}
Update 2:
The last bit of code you show could be done as follows. This takes advantage of the the fact that {% include arg %} "resolves" its argument. This means it can be a variable or a method reference that returns a usable string value that is a template name.
{% for app in apps %}
{% include app %} <!-- or perhaps {% include app.template %} -->
{% endfor %}
Note: Django's template code does not handle top level callables correctly. This means your context cannot pass a reference to a function and expect it to be called and it's output inserted when referenced in a template. Ie. in the example above your list of apps may not be simple functions which you wish to be called. To work as expected a function reference must be either a member of a list or dict, or it must be a method of an object that is passed. We MonkeyPatched this problem long ago because we use curried functions in cached template fragments to defer some heavy DB work. This ticket has been open for over 2 years.

How do I DRY up common text in a Django template?

I have some static text that needs to show up at 2 locations within a template.
For example:
<div>
{% if something %}
This is a static text
{% else %}
Something else happened
{% endif %}
</div>
... more html
<span>
{% if something %}
This is a static text
{% else %}
Something else happend
{% endif %}
</span>
I can do the above by duplicating the above text at 2 different locations in my template file(as shown above).
I could also create a model which will store the text(This is DRY but cost a call to the DB for a simple task)
I'm thinking of using include template but that's probably not the best way to achieve my goal.
What's the best way to do it?
Definitely use Inclusion Tags:
http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
The tag file would either be something super simple like just the text "This is a static text" or the entire block:
{% if something %}
This is a static text
{% else %}
Something else happened
{% endif %}
"something" can be passed as a variable to the template tag so you can use that entire block in a variable way.
I use the django internationalization to do that. So in my apps/template I just write the key, and in the .po files is the value of the keys.
{% load i18n %}
<div>
{% if something %}
{% trans "static" %}
{% else %}
{% trans "something else" %}
{% endif %}
</div>
And in my .po file:
msgid "static"
msgstr "This is a static text"
msgid "something else"
msgstr "Something else happened
Besides useful for multi-language, it's much easier for copy writing just in case you want to change it in the future because you can just look unto one file instead of browsing several templates.
There are several ways, but it probably depends on what the text is and how often it will be used. It's hard to recommend a specific choice without full details
Create a custom template tag (this one makes the most sense based on how you've described your problem above).
Create a base template which has the text in it at the correct location and then inherit off of it for your "2 locations"
Put the static piece of text in a settings file and pass it to the template renderer via Context (probably not the best idea, but depending on what you're doing it could be a possibility)
You could use flatblocks : http://github.com/zerok/django-flatblocks
or chunks : http://code.google.com/p/django-chunks/
Those may be overkill for your problem, since they store your snippets in the database, but they add the benefit of making it possible to edit them via the admin.
{% load chunks %}
<div>
{% if something %}
{% chunk "something" %}
{% else %}
{% chunk "something_else" %}
{% endif %}
</div>
There are lots of forks or similar projects, for example:
http://bitbucket.org/hakanw/django-better-chunks/
http://github.com/bartTC/django-generic-flatblocks
I have a file like Java properties that I use for all of my resource strings. I just serve up the one that I want. Keeping these in one place also makes translating easy.
Ex.:
welcome_msg="hello user!"
thank_you="thank you"
goodbye_msg="goodbye, " + thank_you
If the included text gets bigger, use an 'include' tag.
{% include "myapp/helptext.html" %}
GrtzG