Add total column with django-filter and paged (Django)

0

It is possible to add the columns of totals from django so that for example, it brings me the total of all the sales but ignores the pagination when adding the values.

This is my model:

class Venta(models.Model):
    cliente = models.CharField(max_length=300, verbose_name='Cliente')
    fecha =  models.DateField(auto_now_add=True)
    descripcion = models.CharField(max_length=300, blank=True, verbose_name='Detalle del pedido')
    total = models.DecimalField(decimal_places=2, max_digits=7, verbose_name='Total de la venta')

    def __str__(self):
        return '{}'.format(self.id)

The filters I did with the django-filter library

class VentasFilter(django_filters.FilterSet):
    min_date = django_filters.DateFilter(name="fecha", lookup_expr='gte')
    max_date = django_filters.DateFilter(name="fecha", lookup_expr='lte')
    min_total = django_filters.NumberFilter(name="total", lookup_expr='gte')
    max_total = django_filters.NumberFilter(name="total", lookup_expr='lte')
    class Meta:
        model = Venta
        fields = ['cliente','min_date', 'max_date','min_total','max_total']

And here the view of the sales list:

def filterVenta(request):
    venta_list = Venta.objects.all().order_by('-id')
    venta_filter = VentasFilter(request.GET, queryset=venta_list)
    venta_list = venta_filter.qs
    paginator = Paginator(venta_list,10)
    page = request.GET.get('page')
    try:
        ventas = paginator.page(page)
    except PageNotAnInteger:
        ventas = paginator.page(1)
    except EmptyPage:
        ventas = paginator.page(paginator.num_pages)
    return render(request, 'venta/venta_filter.html', {'filter': venta_filter,'ventas': ventas})

With which I do not have any problem but I would like to add all the totals but I do not recognize the paging or if there are 100 sales that bring me the total of 100 sales and not just the total of the 10 that are on the page and likewise when there is a filter that brings me the total of all those filter sales.

Previously when I did not have paging, I did it from the client with jquery but now that I have paging, I need to do the sum from the backend (django).

Here is my template where I made the addition but with jquery in case someone serves:

{% extends 'base/base.html' %}
{% load widget_tweaks %}
{% block titulo %}Filtros de ventas{% endblock %}
{% block contenido %}
  <nav aria-label="breadcrumb">
    <ol class="breadcrumb">
      <li class="breadcrumb-item"><a href="{% url 'venta:venta_crear' %}">Registrar venta</a></li>
      <li class="breadcrumb-item active" aria-current="page">Ventas</li>
    </ol>
  </nav>
   <form method="get">
    <div class="spaceFilter">
    <div class="card border-info">
      <div class="card-body">
        <h5 class="font-weight-bold">Filtros de ventas:</h5>
        <div class="row">
          <div class="form-group col-sm-4 col-md-3">
            <label for="cliente"><i class="fa fa-user"></i> Cliente: </label>
            {% render_field filter.form.cliente class="form-control" %}
          </div>
        </div>
        <div class="row">
          <div class="form-group col-xs-6 col-sm-3 col-md-3">
            <label for="desdeDate"><i class="fa fa-calendar"></i> Desde: </label>
            {% render_field filter.form.min_date class="form-control" %}
          </div>
          <div class="form-group  col-xs-6 col-sm-3 col-md-3">
            <label for="hastaDate"><i class="fa fa-calendar"></i> Hasta: </label>
            {% render_field filter.form.max_date class="form-control" %}
          </div>
          <div class="form-group col-xs-6 col-sm-3 col-md-3">
            <label for="desdeMonto"><i class="fa fa-dollar"></i> Monto desde: </label>
            {% render_field filter.form.min_total class="form-control" %}
          </div>
          <div class="form-group col-xs-6 col-sm-3 col-md-3">
            <label for="hastaMonto"><i class="fa fa-dollar"></i> Monto hasta: </label>
            {% render_field filter.form.max_total class="form-control" %}
          </div>
        </div>
      <div class="col-md-4 offset-md-4">
      <button type="submit" class="btn btn-primary btn-block btn-md">
        <span><i class="fa fa-filter"></i></span> Filtrar
      </button>
      </div>
      </div>
    </div>
    </div>
  </form>
  <div class="table-responsive-md">
    <table class="table table-striped" id="tabla-today">
      <thead class="thead-dark">
        <tr>
          <th scope="col">#</th>
          <th scope="col">Fecha de venta</th>
          <th scope="col">Cliente</th>
          <th scope="col">Descripción del pedido</th>
          <th scope="col">Total de la venta</th>
          <th scope="col">Acciones</th>
        </tr>
      </thead>
      <tbody>
        {% for venta in ventas %}
      <tr>
        <td>{{ venta.id }}</td>
        <td>{{ venta.fecha}}</td>
        <td>{{ venta.cliente }}</td>
        <td>{{ venta.descripcion }}</td>
        <td><span class="total-list">{{ venta.total }}</span></td>
        <td><a href="{% url 'venta:venta_editar' venta.id %}"><i class="fa fa-eye fa-lg spaceIcon" style="color:#007bff"></i></a>
      <a href="{% url 'venta:venta_eliminar' venta.id %}"><i class="fa fa-trash fa-lg colorDnicos"></i></a>
    </td></td>
      </tr>
    {% empty %}
      <tr>
        <td colspan="8" class="text-center colorVacio">No existen ventas</td>
      </tr>
    {% endfor %}
      </tbody>
      </table>
  </div>
  <span class="current">
        Pagina <span class="colorDnicos">{{ ventas.number }}</span> de
        <span class="colorDnicos">{{ ventas.paginator.num_pages }}</span>.
    </span>
    <ul class="pagination justify-content-center">
        {% if ventas.has_previous %}
            <li class="page-item"><a class="page-link" href="?page=1">&laquo; Inicio</a></li>
        <li class="page-item"><a class="page-link" href="?page={{ ventas.previous_page_number }}">Previous</a></li>
        {% endif %}
        {% for i in ventas.paginator.page_range %}
          {% if ventas.number == i %}
            <li class="page-item active"><span class="page-link">{{ i }} <span class="sr-only">(current)</span></span></li>
          {% else %}
            <li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
          {% endif %}
        {% endfor %}
        {% if ventas.has_next %}
        <li class="page-item"><a class="page-link" href="?page={{ ventas.next_page_number }}">Next</a></li>
        <li class="page-item"><a class="page-link" href="?page={{ ventas.paginator.num_pages }}">Ultimo &raquo;</a></li>
        {% endif %}
    </ul>
  <div class="row justify-content-center spaceIndicador">
      <div class="card border-info mb-3" style="max-width: 18rem;">
        <div class="card-header">Total de ventas</div>
        <div class="card-body text-info">
          <p class="card-text">EL monto es de: S/.<span class="totalVentas font-weight-bold"></span></p>
        </div>
      </div>
    </div>
{% endblock %}
{% block javascript %}
    <script type="text/javascript">
      $(document).ready(function(){
        $('#id_min_date').datetimepicker({
            format: 'DD/MM/YYYY',
            locale: 'pe'
        });
        $('#id_max_date').datetimepicker({
            format: 'DD/MM/YYYY',
            locale: 'pe'
        });
        //Calculo de totales
          var sum = 0;
          $(".total-list").each(function(){
          sum += parseFloat($(this).text().replace(',', '.'));
        });
        $('.totalVentas').text(sum.toFixed(2));
      });
    </script>
{% endblock %}
    
asked by Piero Pajares 19.03.2018 в 21:10
source

1 answer

0

Solved (: In case someone ever needs something similar here the solution: simply in my function I added to the filter:

suma_total = venta_filter.qs.aggregate(Sum('total'))

and obviously with another variable to send the arguments to the template:

return render(request, 'venta/venta_filter.html', {'filter': venta_filter,'ventas': ventas, 'total': suma_total})

and in the template we can access the total that always puts the name with which you are sending with the arguments and adding __sum:

{{total.total__sum}}

and staying as:

def filterVenta(request):
    venta_list = Venta.objects.all().order_by('-id')
    venta_filter = VentasFilter(request.GET, queryset=venta_list)
    suma_total = venta_filter.qs.aggregate(Sum('total'))
    venta_list = venta_filter.qs
    paginator = Paginator(venta_list,10)
    page = request.GET.get('page')
    try:
        ventas = paginator.page(page)
    except PageNotAnInteger:
        ventas = paginator.page(1)
    except EmptyPage:
        ventas = paginator.page(paginator.num_pages)
    return render(request, 'venta/venta_filter.html', {'filter': venta_filter,'ventas': ventas, 'total': suma_total})

I hope you serve someone (:

Update it happened to me that if I page it, but when I went to page 2, I would remove the filter and throw the data again without the filter, then solve it in the following way in the template:

<span class="current">Pagina <span class="colorDnicos">{{ ventas.number }}</span> de<span class="colorDnicos">{{ ventas.paginator.num_pages }}</span>.</span>
    <ul class="pagination justify-content-center">
        {% if ventas.has_previous %}
        <li class="page-item"><a class="page-link" href="?page=1{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">&laquo; Inicio</a></li>
        <li class="page-item"><a class="page-link" href="?page={{ ventas.previous_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Previous</a></li>
        {% endif %}
        {% for i in ventas.paginator.page_range %}
          {% if ventas.number == i %}
            <li class="page-item active"><span class="page-link">{{ i }} <span class="sr-only">(current)</span></span></li>
          {% else %}
            {% if forloop.counter <= 5 %}
              <li class="page-item"><a class="page-link" href="?page={{forloop.counter}}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">{{forloop.counter}}</a></li>
            {% endif %}
          {% endif %}
        {% endfor %}
        {% if ventas.has_next %}
        <li class="page-item"><a class="page-link" href="?page={{ ventas.next_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Next</a></li>
        <li class="page-item"><a class="page-link" href="?page={{ ventas.paginator.num_pages }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Ultimo &raquo;</a></li>
        {% endif %}
    </ul>
    
answered by 20.03.2018 / 01:34
source