goku
goku

Reputation: 117

When displaying foreign key base Queryset on template

I have two models shown below

class Services(models.Model):

    name = models.CharField(max_length=200, null=True)
    price = models.FloatField(null=True)
    service_sku = models.CharField(max_length=200, null=True)


class Order(models.Model):

    customer = models.ForeignKey(Customer, null=True, on_delete = models.SET_NULL)
    service = models.ForeignKey(Service, null=True, on_delete = models.SET_NULL)

I have created a function-based view based on the service model where I want to render a template displaying a list of field information from each instance from the service model.

See below for my views and template

views.py 

def service_list(request):

    service_list = Service.objects.all().order_by('service_sku')


    context = {'service_list':service_list}

    return render(request, 'accounts/service_list.html',context)

template

            <div class="card card-body">
                    <table class="table">
                        <tr>
                            <th>SKU</th>
                            <th>Service Name</th>
                            <th>Number of Ordered</th>

                        </tr>

            {% for i in service_list %}



                            <tr>
                                <td>{{i.service_sku}}</td>
                                <td>{{i.name}} </td>
                                <td></td>

                            </tr>

                            {% endfor %}

I want to display the number of orders of each instance, considering that the order model has a foreign key from the service model.

The query set would have to be like the below shown.

Order.objects.all().filter(service__id =3).count()

Problem is that I must specify which id of that model would be for that queryset to work.

I’ve tried to put the queryset format below within the template

{{Order.objects.all().filter(service__id=i.id).count()}

In the template it would look like how it does below

template

            <div class="card card-body">
                    <table class="table">
                        <tr>
                            <th>SKU</th>
                            <th>Service Name</th>
                            <th>Number of Ordered</th>

                        </tr>

            {% for i in service_list %}



                            <tr>
                                <td>{{i.service_sku}}</td>
                                <td>{{i.name}} </td>
                                <td>{{Order.objects.all().filter(service__id=i.id).count()}}</td>

                            </tr>

                            {% endfor %}

The above implementation does not work.

Which method is ideal for this situation?

Upvotes: 2

Views: 142

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477437

You can not call methods (with parameters) in a Django template. The templates are deliberately restricted to prevent people from writing business logic in the templates.

You can .annotate(…) [Django-doc] the queryset to fetch the number of related Orders:

from django.db.models import Count

def service_list(request):
    service_list = Service.objects.annotate(
        norders=Count('order')
    ).order_by('service_sku')
    context = {'service_list':service_list}
    return render(request, 'accounts/service_list.html',context)

In the template you can then render this with:

{% for i in service_list %}
<tr>
    <td>{{ i.service_sku }}</td>
    <td>{{ i.name }} </td>
    <td>{{ i.norders }}</td>
</tr>
{% endfor %}

Upvotes: 1

Related Questions