Django: Unused 'v_item.pk' at end of if expression

Viewed 566

I'm trying to hide a button if the ID already exist in other table. I have a Confirm button in my template that i use to confirm orders and it save the confirmed orders in a table called (ConfirmOrder). So i want if order is already confirmed or the id of that order already exist in ConfirmOrder table the confirm button is disabled/hidden so that i cannot confirm it again. I tried to use templatetags i get this error (Unused 'v_item.pk' at end of if expression)

Model

class ConfirmOrder(models.Model):
    order_no = models.ForeignKey(OrderDetail, related_name='confirmorders', on_delete = models.SET_NULL, null=True)
    product = models.ForeignKey(StoreStock, null=True, blank=True, on_delete = models.SET_NULL)
    quantity = models.DecimalField(max_digits = 10, decimal_places = 2, blank=True)
    buying_price = models.DecimalField(max_digits = 10, decimal_places = 2, blank=True)
    amount = models.DecimalField(max_digits = 10, decimal_places = 2, blank=True)
    confirm_note = models.CharField(max_length = 50, blank=True)
    is_active = models.IntegerField(default=1)

Template tag

from django import template
from ..models import ConfirmOrder

register = template.Library()

@register.simple_tag
def check_item_already_exists(request, pk):
    return ConfirmOrder.objects.filter(id=pk, is_active=1).exists()

Templates

{% for v_item in viewitem %}
  <tr>
    <td>{{ forloop.counter }}</td>
    <td>{{ v_item.order_no.location }}</td>
    <td>{{ v_item.order_no.order_date }}</td>
    <td>{{ v_item.order_no.supplier }}</td>
    <td>{{ v_item.order_no.order_number }}</td>
    <td>{{ v_item.order_no.pay_ref }}</td>
    <td>{{ v_item.product }}</td>
    <td>{{ v_item.quantity }}</td>
    <td>{{ v_item.buying_price }}</td>
    <td>{{ v_item.amount }}</td>
    <td>
      {% load check_item %}
      {% if not check_item_already_exists v_item.pk %}
      <a class="btn btn-warning btn-sm" href="{% url 'confirm_order' v_item.pk %}"> Confirm </a>
      {% endif %}
    </td>

View

def confirm_purchase(request):
    viewitem = OrderItem.objects.all()
    return render(request, 'managepurchase/confirmed_purchase.html', {'viewitem': viewitem})

Where am i doing wrong? or is there any other way i can do this? Can any one help please!

2 Answers

Please do not write business logic in the template. A template deals with rendering logic. Not with business logic. The Django template language is deliberately restricted to avoid people writing a lot of business logic in the template.

In the view you can .annotate(…) [Django-doc] the QuerySet with:

from django.db.models import Exists, OuterRef

def confirm_purchase(request):
    viewitem = OrderItem.objects.annotate(
        is_active=Exists(
            ConfirmOrder.objects.filter(is_active=1, pk=OuterRef('pk'))
        )
    )
    return render(request, 'managepurchase/confirmed_purchase.html', {'viewitem': viewitem})

then in the template we can render it with:

{% if v_item.is_active %}
    <a class="btn btn-warning btn-sm" href="{% url 'confirm_order' v_item.pk %}"> Confirm </a>
{% endif %}

Your line

{% if not check_item_already_exists v_item.pk %}

contains 2 parts (check_item_already_exists and v_item.pk) for the condition, but only one part is allowed.

You cannot pass arguments to a function call inside Django templates (that is a design decision in Django), so you will have to find another way to get the info you need in the template, maybe by calling the function in the view instead of in the template.

Related