Reputation: 11
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:
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
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