Using Custom Template Tag Inside Built in tags of Django

66 Views Asked by At

I have created a simple tag as below.

 @register.simple_tag(takes_context=True,name="calculate_billamount")
       def calculate_billamount(quantity,unitprice):    
          return (quantity * unitprice)

     {% for order_detail in order_details %}
       {% if order_detail.orderid == order %}    
           <tr>
                <td>{{order_detail.productid.productname}}</td>
                <td>{{order_detail.unitprice}}</td>
                <td>{{order_detail.quantity}}</td>   
                <td>{% calculate_billamount quantity=5 unitprice=4 %} </td>                                     

                <td>{{billamount}}</td>
         </tr>
     {% endif %}               
    {% endfor %}

This is just multiplying 2 numbers and returning the result.

I am trying to use above simple tag inside a FOR and IF as shown below.

I am getting below error. enter image description here

when i try this individually, i am not getting any error i.e. it is working fine.

        <div>
        {% calculate_billamount quantity=5 unitprice=4 %}
    </div>

Is there any restriction, that we cant use Custom Simple Template tags inside django built in template tags like for and if?

Thanking you.

2

There are 2 best solutions below

1
Sri Vidya On

{% load custom_tags %} needs to be placed in both html pages.

My Scenario :

First.html -> is using {%show_orders%} template tag which is displaying results in Second.html with the help of Inclusiontag.

Now when I try to use "Calculate_billamount" custom tag in second.html, it was giving an error. So i had to put {% load custom_tags %} in Second.html too.

Thank you all.

0
Maxim Danilov On

First:

I am agree with Sri Vidya, i dont see {% load custom_tags %} before using calculate_billamount, this is one error.

 {% load custom_tags_with_calculate_billamount %}
 {% for order_detail in order_details %}
   {% if order_detail.orderid == order %}    
            <-- any staff -->
            {% calculate_billamount quantity=5 unitprice=4 %}
   {% endif %}               
{% endfor %}

don't forget. {% calculate_billamount quantity=5 unitprice=4 %} will render it directly, without wariables assessment. I mean - you dont have billamount variable here.

Second. AS - syntax:

You can use {% calculate_billamount quantity=5 unitprice=4 as billamount %} In this case you add a variable billamount in context. But it will be not rendered automatically, you should do it yourself:

 {% for order_detail in order_details %}
   {% if order_detail.orderid == order %}    
       <-- any staff -->
       {% calculate_billamount quantity=5 unitprice=4 as billamount %}
       {{billamount}}
   {% endif %}               
{% endfor %}

Third. Takes context=True

Your code simply not works. takes_context=true add context of template as a first attribut.

@register.simple_tag(takes_context=True,name="calculate_billamount")
def calculate_billamount(context, quantity, unitprice):    
   return (quantity * unitprice)

read more here: https://docs.djangoproject.com/en/5.0/howto/custom-template-tags/#howto-custom-template-tags-inclusion-tags

Forth:

For two attributes you can define filter:

@register.filter
def calculate_billamount(quantity, unitprice):    
  return (quantity * unitprice)

After you can use it in template:

{{ quantity|calculate_billamount:unitprice }}

read more here: https://docs.djangoproject.com/en/5.0/howto/custom-template-tags/#writing-custom-template-filters

Fifth. YAGNY:

I believe - you made all overcomplicated. Simply write in template:

{{ quantity * unitprice }}

Of corse, in my answer i skip multiple other questions, like: why not change context in template_tag, why using custom template_tags is a bad practice, and many other things. And i am totally agree with comments from @McPherson: it seems, like billamount should be as a calculated property of any bill.