CodingSexagenarian
CodingSexagenarian

Reputation: 11

Why is My Ordered List with Template Variable is Showing the Numeral One for Each Entry?

I'd appreciate your help figuring out why my ordered list with template variables shows the numeral one for each entry. I'd also like to know how to correct this and present an ascending list.

Here's what's happening: I am trying to show the top three selling items. One of the top items has a three-way tie, so I should show five items. I see five items, but each is labeled as number one.

Here's what it looks like:

enter image description here

Here's my code:

views.py

class ReportView(LoginRequiredMixin, TemplateView):
    template_name = "inventory/reports.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["purchases"] = Purchase.objects.all()
        revenue = Purchase.objects.aggregate(
            revenue=Sum("menu_item__price"))["revenue"]
        total_cost = 0
        for purchase in Purchase.objects.all():
            for recipe_requirement in purchase.menu_item.reciperequirement_set.all():
                total_cost += recipe_requirement.ingredient.unit_price * \
                    recipe_requirement.quantity

        purchases = Purchase.objects.values(
            'timestamp',
            item_name=F('menu_item__name'),
            item_price=F('menu_item__price'),
            item_desc=F('menu_item__description'))
        df = read_frame(purchases)
        grouped_purchases = df.groupby('item_name')[
            'timestamp'].count().reset_index()
        sort_purchases = grouped_purchases.sort_values("timestamp", axis=0,
                                                       ascending=False,
                                                       ignore_index=True)
        top_3 = sort_purchases.nlargest(3, 'timestamp', keep='all')
        list_of_top_3_purchases = top_3['item_name'].to_list()

        context["revenue"] = revenue
        context["total_cost"] = total_cost
        context["profit"] = revenue - total_cost
        context["gross_profit"] = (revenue - total_cost) / total_cost * 100
        context["gross_margin_ratio"] = (revenue - total_cost) / revenue * 100
        context["list_of_purchases"] = list_of_top_3_purchases

        return context

reports.html

...
     <section
            style="color: black;"><h2>Top 3 Purchases</h2>
         {% for item in list_of_purchases %}
            <ol>
                  <li>{{ item }}</li>
            </ol>
         {% endfor %}
     </section>
...

To take this to the next level, I'd like to know how to show the tied items with the same number. Any help you can provide will be gratefully appreciated. Thanks.

Upvotes: 0

Views: 47

Answers (1)

SamSparx
SamSparx

Reputation: 5257

You are getting repeated ones because in your loop you are creating a new ordered list each time, which restarts the counting. Your HTML will look like this

        <ol>
              <li>PB&J</li>
        </ol>
        <ol>
              <li>Vege Pizza</li>
        </ol>

However, just putting the loop inside a single <ol>...</ol> tag won't help you with your repeating numbers. You will need to assign the number based on the result somehow. This is best handled in the view.

nb: The following is pseudocode as I'm not superfamiliar with numpy, so it won't work, but should give you the idea of what you need to do:

assumes descending order of timestamp

current_count = 0
#set intial current_value to first top_item's value
current_value = top_3[0]['timestamp']

#loop thrru top_3
for top_item in top_3:
    # if value of timestamp is changed, increment count and set current_value to timestamp
    if current_value < top_item['timestamp']:
         current_count += 1             
         top_item['count'] = current_count
         current_value = top_item['timestamp']

    else:
         #it's an equal value, so we just set the count to the current value
         top_item['count'] = current_count

then, in your html

 <section
        style="color: black;"><h2>Top 3 Purchases</h2>
     <ol>
     {% for item in list_of_purchases %}
          <li>{{item.count}}. {{ item.name }}</li>
     {% endfor %}
     </ol>

Upvotes: 1

Related Questions