django - multiplication and templates - python

I hope you can help me on this one. I have a template that shows the price of a, lets say a Banana, and for example the banana costs $400 and i have to calculate the 21% of this price and show it on a box of a table. I was tempted to do something like:
{% for banana in bananas %}
{{banana.price}}*(21%)
{% endfor %}
but obviously that failed miserably.
So, is there a way to do this type of simple equations in a template or i need to make a custom template tag to handle it.
its a very basic question but i would really appreciate the help.
Thank you.

You do need a custom template tag, but you could install django-mathfilters, which provides such basic operations:
{% load mathfilters %}
...
{{banana.price|mul:0.21}}
Taken from the mathfilters page, the included operations are:
sub – subtraction
mul – multiplication
div – division
abs – absolute value
mod – modulo
'Add' is provided in Django as standard.

You can use built-in widthratio template tag:
For creating bar charts and such, this tag calculates the ratio of a
given value to a maximum value, and then applies that ratio to a
constant.
{% widthratio banana.price 100 21 %}

Related

Applying CSS classes to table rows with Sphinx and reStructuredText

We have a website that is generated using Sphinx and reStructuredText. Albeit not ideal (I have inherited this code), it's something that so far has worked and serves the purpose. We're trying to extend it slightly and one request was to highlight better certain rows in a table based on a condition (just a bit of context).
What we noticed is that if the element that needs the style applied is the first one in the for-loop, the style gets instead applied to the parent (<tbody>) element.
This is the relevant piece of code that does not seem to be working as intended:
{% for codelist_item in codelist_json.data %}
{% if codelist_item.status == 'withdrawn' %}
.. rst-class:: withdrawn
* - {{codelist_item.code + " (withdrawn)"}}
{% else %}
* - {{codelist_item.code}}
{% endif %}
- {{codelist_item.name}}
...
{% endfor %}
NB: indentation is correct (as in it matches what's in our rst file)
Non working example: http://reference.iatistandard.org/202/codelists/BudgetIdentifierVocabulary/
whose HTML is:
<tbody class="withdrawn" valign="top">
<tr class="row-even">
<td>1 (withdrawn)</td>
<td>IATI</td>
<td>The budget identifier reported uses IATI budget identifier categories</td>
</tr>
Working example: http://reference.iatistandard.org/202/codelists/Currency/
<tr class="withdrawn row-even">
<td>BYR (withdrawn)</td>
<td>Belarussian Ruble</td>
<td>Withdrawn from ISO Currency codelist. Use code BYN.</td>
</tr>
While exploring the Sphinx docs, I stumbled across this bit that might be (or at least sounds) relevant
http://docutils.sourceforge.net/docs/ref/rst/directives.html#id12
This allows the "classification" of individual list items (except the first, as a preceding class directive applies to the list as a whole)
That seems to fit our problem, although like I said I'm not entirely sure it does relate to it.
So far, we tried checking {% forloop.first %}, moving the rst-class:: around, but nothing seems to work.
Any advice?

django template show only distinct value

Suppose I have a query:
cities = City.objects.all()
In my template I have done:
{% for city in cities %}
{{city.friend_name}}
View Detail
{% endfor %}
It gives me name of 4 friends with id say alex 1, matt 2, mack 3, mack 3. But here mack is repeated. I only want mack once. If the values are repeated I want it to be printed only once.
How can I do this in template. I mean is there something like {{city.friend_name|distinct}} or something else
I dont want unique city. I want friends name on city to be unique.
Thank you
Don't use extra input parameters, just use the "ifchanged" django builtin filter: https://docs.djangoproject.com/en/2.0/ref/templates/builtins/#ifchanged
{% for city in cities|dictsort:'friend_name' %}
{% ifchanged %}{{city.friend_name}}{% endifchanged %}
View Detail
{% endfor %}
p.s. i know it's 3 years old but it's an helpful answer for someone else.
It is usually best to change your Query first to ensure you get the least amount of data.
In this case, you could edit your query as follows:
cities_with_uniq_friend_names = City.objects.all().distinct('friend_name')
Now when you iterate over cities_with_uniq_friend_names it will give you unique friend names
Why do you want to do it in the template? Try to modify cities itself so that it has unique entries.
You could convert your list to a set and then re-convert it back:
cities_unique = list(set(cities))
If you have to show unique attributes, use the regroup feature

Paginated based on the alphabet (A-Z)

I have a simple contacts application where I want to paginate the contact list based on first name alphabet.
Here is my views.py
def contacts(request):
contact_list = Contact.objects.filter(user=request.user).order_by('first_name')
return render(request, 'contact/contact.html', {'contact_list': contact_list})
Here is my template
<ul>
{% for contact in contact_list %}
<li>{{ contact.first_name }}</li>
{% endfor %}
</ul>
Is there a default way in Django that does this? There is Django pagination but I think that only splits data across pages. What would be the easiest way to do so?
It seems a letter-wise paginator does not exist by default. Pages like https://djangosnippets.org/snippets/1364/ <<< this one show hand-made implementations.
However, it's not so hard to implement: you can base yourself on startswith keyword and:
pages = [myQuerySet.filter(myfield__istartswith=i) for i in "ABC...XYZ"] #full alphabet here
(let myQuerySet be, actually, contact_list; let myfield be, actually, first_name).
I've done this once, by adding a letter field to my model and "paginating" manually. This raised a lot of interesting situation with foreign alphabets. Found this useful: https://pypi.python.org/pypi/Unidecode
Didn't find any "smarter" way to go about it. But I'd be interested in hearing about more "plug-n-play" solution...

two or more dots in a django template after the variable

In a django template, is it possible to have two (or more) dots after a variable? For example, say I have a list of objects that I first want to use a list-index lookup for and then once I have the object, I want to call its method for getting the absolute url, should that work?
For example:
{% for entry in myList %}
{{ entry.0.get_absolute_url }}
{% endfor %}
So the 0 is asking for the first item in the list which is an object, then I want to get the absolute url. It doesn't work when I try it but it doesn't return an error either. Is there a better way to accomplish what I'm trying to do?
To clarify it, what's strange is that:
This works:
{{ singleObject.get_absolute_url }}
In that case if I just try {{ singleObject }}, I get the unicode value of that object so something like: John Smith
This doesn't work:
{% for object in objectList %}
{{ object.get_absolute_url }}
{% endfor %}
But in this case, if I put in {{ object }}, I no longer get the unicode value. I get: [<Name: John Smith>] (name being the name of the model)
Basically, the method works when it's outside of a loop. Could there be any reason for that?
more than one dot absolutely works.
based on your comment, there is no entry.0 because entry IS the first item in the list cause you are already looping through `myList'
just use entry.get_absolute_url instead
but if you only want to print out the url for the first entry, forgo the for loop and just use myList.0.get_absolute_url
UPDATE:
there's a tip from 'the pragmatic programmer' that says:
``select’’ Isn’t Broken
It is rare to find a bug in the OS or the
compiler, or even a third-party product or library. The bug is most
likely in the application.
i think you assumed that django templates were behaving weird, when the truth is you were not building your list correctly. don't be afraid to show some of your actual code, by abstracting the problem for us, you removed the part that included the problem
I got it. I had brackets around each item in my list like so:
objectList = [['John Smith'], ['Jim Jones'], ['Bill White']]
Silly me! Thanks so much for your all your input
What you are doing is perfectly acceptable in Django templates. There is no better way to accomplish what you're trying to do.

Google appengine string replacement in template file

I'm using google appengine (python, of course :) ) and I'd like to do a string.replace on a string from the template file.
{% for item in items %}
<p>{{ item.code.replace( '_', ' ' ) }}</p>
{% endfor %}
But that isn't working. So we cannot execute anything other than basic checks in the app engine templates. Is that Correct ?
Another related problem is I'm trying to shorten a string and make it available to the template.
Each furniture object has a name and a longer description field. In this view I'm rendering, I want only the first 50 characters of the description field.
So I tried something like
items = db.GqlQuery( 'select * from furniture' )
# edit: if you change the above line to
# items = db.GqlQuery( 'select * from furniture' ).fetch( 1000 )
# the .fetch() command makes the addition of dynamic properties work!
for item in items :
item.shortdescr = item.description[ 0:50 ]
# pass data off to template for rendering
self.response.out.write(
template.render( 'furnitureAll.html', { 'items' : items } )
)
Template goes
{% for item in items %}
<p>{{ item.name }}</p>
<p>{{ item.shortdescr }}</p>
<!-- items.shortdescr does not exist here,
probably because I did not .put() it previously. -->
{% endfor %}
Since that didn't work, I tried changing the Gql Query to shorten the string instead. But I'm quickly realizing Gql isn't like SQL. I'm trying to write queries like
select name,LEFT( description, 50 ) from furniture
With little success
I have little experience with Google AppEngine, but my understanding is that it is very closely related to Django. Your templates do not actually contain Python code, even if some of the structures you use in them look like it.
Both of your questions should be solved using template filters. If it was Django, I would use something like this for your second question:
{{ item.description|truncatewords:10 }}
For your first question (string replace), there may be no built-in filter you can use for that. You will need to write your own. Something like this;
from google.appengine.ext.webapp.template import create_template_register
register = create_template_register()
#register.filter
def replace_underscores(strng):
return strng.replace('_', ' ')
Then, in your template, you can do this:
{{ item.code|replace_underscores }}
Apart from the argument-less .fetch() call in your code, which I believe can't possibly work (you ALWAYS have to pass fetch an argument -- the max number of entities you're willing to fetch!), I can't reproduce your problem -- assigning a new attribute (including one obtained by processing existing ones) to each item just works fine in my tests.
Can you please reproduce your observed problem in as tiny as compass as possible and edit your question to include all relevant files pls? Seems to be the only way we could help you with your weird observed bug!
BTW, select name,LEFT( description, 50 ) or whatever OF COURSE won't work in GQL -- GQL, very very explicitly, ONLY supports select * to get whole entities, or select __key__ to get just the entities' keys -- that's all; NO selectivity of columns in the select, much less any OPERATIONS on them!-)

Categories