0

I need to aggregate data from an Order table to be able to determine the total amount of items sold per date .

My order model looks like this:

class Order(models.Model):
    guest = models.ForeignKey('hotel.Guest', on_delete=models.CASCADE)
    date = models.DateField(auto_now_add=True)
    amount = models.IntegerField()
    item = models.ForeignKey('hotel.Item', on_delete=models.CASCADE)
    price = models.IntegerField(default=1)
    is_paid = models.BooleanField(default=False)
    paid_date = models.DateField(blank=True, null=True)

I have now created a view that iterates over time and date:

def listAllOrders(request):
    context = {}
    orders = Order.objects.exclude(item__name = 'Room Rate')
    item_dates = orders.values('date')
    item_date = item_dates.order_by('date').distinct('date')
    item_ids = orders.values('item__name')
    item_id = item_ids.order_by('item__name').distinct('item__name')
    inventory  = []
    for d in item_date:
        for i in item_id:
            q=Order.objects.filter(item__name=i['item__name'], date=d['date'])
            ta=q.aggregate(total_amount = Sum('amount'))
            tp=q.aggregate(total_price = Sum('price'))
            inventory.append([d['date'],i['item__name'],ta,tp])

    context['inventory'] = inventory
    #context = Order.objects.all()
    return render (request, 'hotel/inventory.html', context)

how can I now fill this data in a table in my template. If I give a queryset to context I usually do this like this:

<table class="table table-condensed table_orders">
    <tr>
        <th>Date</th>
        <th>Amount</th>
        <th>Item</th>
    </tr>

{% for Order in inventory %}
<tr>
    <td>{{ Order.date }}</td>
    <td>{{ Order.amount }}</td>
    <td>{{ Order.item }}</td>
</tr>

{% endfor %}
</table>

This obviously doesn't work here because the data in inventory is not structured.. how can I solve this?

1 Answer 1

2

As per the Django's Variable and Lookup Document:

Dots have a special meaning in template rendering. A dot in a variable name signifies a lookup. Specifically, when the template system encounters a dot in a variable name, it tries the following lookups, in this order:

Dictionary lookup. Example: foo["bar"]

Attribute lookup. Example: foo.bar

List-index lookup. Example: foo[bar]


In your inventory list, you appending another list. Instead, append it in the form of `dict. i.e. replace:

inventory.append([d['date'],i['item__name'],ta,tp])

with:

inventory.append({'date': d['date'],
                  'name': i['item__name'],
                  'amount': ta,
                  'price': tp})

and within your template, access it like:

{% for Order in inventory %}
    <tr>
        <td>{{ Order.date }}</td>   
        <td>{{ Order.name }}</td>
        <td>{{ Order.amount }}</td>
        <td>{{ Order.price }}</td>
    </tr>
{% endfor %}

Alternatively, if you want to access list in the template (suggested approach over here is by using map, but explaining for the illustration purpose) i.e. if you do not want to make any change in your current view, then access the items in your list based on the index. For example:

{% for Order in inventory %}
    <tr>
        <td>{{ Order.0 }}</td>   
        <td>{{ Order.1 }}</td>
        <td>{{ Order.2 }}</td>
        <td>{{ Order.3 }}</td>
    </tr>
{% endfor %}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.