3

I've a page that shows the will show the monthly revenue, according to what user selects as month.

In HTML there is a with all the possible inputs. Now in my

I'm returning a new variable for use in the template, **not a queryset**. I just want to put `{{ revenue }}` in the template.

I've read that I don't need to send a post, only with a get I can achieve this. So I've set up this form to capture selected month, but I'm getting:

TypeError at /ordenes/ingresos
unhashable type: 'slice'

How should I set the context in the get_queryset method?

Views.py

class OrdersListView(ListView):

    model = Order
    template_name = "order/revenue.html"
    paginate_by = 10

    def get_queryset(self):
        filter_month = self.request.GET.get('filtromes', '0')
        order = self.request.GET.get('orderby', 'created')
        context = {}
        if filter_month == "0":
            paid_orders = Order.objects.filter(status = 'recibido_pagado')
            revenue = 0
            for order in paid_orders:
                revenue += order.total - order.shipping_cost 
            context['revenue'] = revenue
            return context
        else:    
            paid_orders = Order.objects.filter(created__month=filter_month).filter(status = 'recibido_pagado')
            #orders_shipping = Order.objects.filter(created__month=9).filter(status = 'recibido_pagado')
            revenue = 0
            for order in paid_orders:
                revenue += order.total - order.shipping_cost 
            context['revenue'] = revenue
            return context

    def get_context_data(self, **kwargs):
        context = super(OrdersListView, self).get_context_data(**kwargs)
        #filter_month = self.request.GET.get('filtro_mes', '0')
        context['filtromes'] = self.request.GET.get('filtromes', '0')
        context['orderby'] = self.request.GET.get('orderby', 'created')
        context['category'] = "catalogo"
        return context

HTML:

<!--### Filter ###-->
     <div class="row margin-top5 margin-bottom5 ">
        <form method="get" action="{% url 'order:ingresos' %}">
            <div class="input-group">
                <div class="input-group-prepend">
                    <label class="input-group-text" for="inputGroupSelect01">Mes</label>
                </div>
                <select class="custom-select" searchable="Search here.." value={{filtromes}} name="filtromes">
                    <option value="0" disabled>Elegir mes</option>
                    <option value="1">Enero</option>
                    <option value="2">Febrero</option>
                    <option value="3">Marzo</option>
                    <option value="4">Abril</option>
                    <option value="5">Mayo</option>
                    <option value="6">Junio</option>
                    <option value="7">Julio</option>
                    <option value="8">Agosto</option>
                    <option value="9">Setiembre</option>
                    <option value="10">Octubre</option>
                    <option value="11">Noviembre</option>
                    <option value="12">Diciembre</option>
                    </select>
                <div class="input-group-append">
                    <input class="btn btn-outline-secondary" type="submit" name="buscar" value="Buscar" style="margin-bottom: 0px;" />
                </div>
            </div>
        </form>
    </div>


    <!--### Filter ###-->

    <h1> {{ revenue }}</h1>
Omar Gonzales
  • 3,806
  • 10
  • 56
  • 120

1 Answers1

2

Instead of trying to force context into get_queryset, you can pull the object_list into get_context_data:

def get_queryset(self):
    filter_month = self.request.GET.get('filtromes', '0')
    if filter_month == "0":
        return Order.objects.filter(status = 'recibido_pagado')
    else:
        return (Order.objects
                .filter(created__month=filter_month, status = 'recibido_pagado'))

def get_context_data(self, **kwargs):
    context = super(OrdersListView, self).get_context_data(**kwargs)
    qs = kwargs.pop('object_list', self.object_list)
    order = self.request.GET.get('orderby', 'created')
    context = {}
    revenue = 0
    for order in qs:
        revenue += order.total - order.shipping_cost 
    context['revenue'] = revenue
    context['filtromes'] = self.request.GET.get('filtromes', '0')
    context['orderby'] = self.request.GET.get('orderby', 'created')
    context['category'] = "catalogo"
    return context

Also consider using annotate, Sum, and/or aggregate to calculate the revenue

jmunsch
  • 22,771
  • 11
  • 93
  • 114
  • ty, it works. However I've this problem now that is not directly related to the view but the template: How to keep last option selected by user in the form? It defaults to "Enero", value="1" (User selects "Setiembre", revenue is calculated based on "Setiembre" but select is set to "Enero")? And would also apreaciate and example using `annotate`, `Sum` or aggregate to calculate `revenue`, what are the benefits? – Omar Gonzales Oct 10 '19 at 01:10
  • @OmarGonzales https://stackoverflow.com/questions/12165636/django-aggregation-summation-of-multiplication-of-two-fields AND forward the value from the self.request.GET/POST if you want a value to stay the same. – jmunsch Oct 10 '19 at 02:58
  • Please, see: https://stackoverflow.com/questions/58330348/add-context-variable-as-an-aggregate-or-annotate-of-2-cols-in-cbvs-get-context – Omar Gonzales Oct 10 '19 at 21:09