Merging Django querysets of differenting size causing date missmatch in graph view with date value

Tengo 2 querysets, cada filtrado por transacciónTipo sobre el mismo rango de fechas, sólo problema es, el queryset están volviendo diferentes tamaños ya que algunas de las fechas no coinciden con el filtro aplicado, así que en lugar de devolver 0 devuelve 'vacío' (o así que creo )

current_date = datetime.today()

months_ago = 6

six_month_previous_date = current_date - timedelta(days=(months_ago * 365 / 12))

aggregatedSales = Transactionlog.objects.using('database').filter(transactiondate__gte=six_month_previous_date).filter(
    transactiontype=1).values('transactiondate').annotate(sales_by_month=Count('transactiondate'))

aggregatedRefunds = Transactionlog.objects.using('database').filter(
    transactiondate__gte=six_month_previous_date).exclude(transactiontype=1).values('transactiondate').annotate(
    ref_by_month=Count('transactiondate'))

transaction_Values_list = list(chain(aggregatedRefunds, aggregatedSales ))

transaction_Values_rules = defaultdict(dict)

for dic in transaction_Values_list:
    transaction_Values_rules[dic['transactiondate']].update(dic)

Mi número es que cuando estos 2 juegos de preguntas se diplayan en un gráfico la longitud diferente causa un partido de la falta en las fechas - im utilizando Chart.js para renderizar las tablas en mi plantilla utilizando el folwing -

    (function ($) {
  $(document).ready(function(){

    var fixedLineChart = $('#fixed-line-chart');
    var fixedLineChartJS = new Chart(fixedLineChart, {
      type: 'line',
      data: {
        labels: [{% for dates in aggregated %}'{{ dates.transactiondate|date:'Y-m-d H:i:s' }}',{% endfor %}],
        datasets: [{
          label: 'Sales',
          data: [{% for sales in aggregated %}'{{ sales.sales_by_month }},{% endfor %}],
          borderColor: chartColorGreen,
          backgroundColor: rgbToRgba(chartColorGreen, '.25'),
          pointBackgroundColor: chartColorGreen,
          pointBorderColor: rgbToRgba(chartColorGreen, '.25'),
          lineTension: 0,
          fill: 'origin',
        },{
          label: 'Refunds',
          data: [{% for ref in aggregated %}'{{ ref.ref_by_month }},{% endfor %}],
          borderColor: chartColorPink,
          backgroundColor: rgbToRgba(chartColorPink, '.25'),
          pointBackgroundColor: chartColorPink,
          pointBorderColor: rgbToRgba(chartColorPink, '.25'),
          lineTension: 0,
          fill: 'origin',
        }]
      },
      options: {
        hover: {
          mode: 'index',
          intersect: false
        },
        maintainAspectRatio: false,
      }
    });

¿Hay alguna manera de hacer esto?

Pregunta hecha hace 3 años, 5 meses, 0 días - Por techtrailblazer


3 Respuestas:

  • Vale, fue una tarea más simple que pensé, simplemente iterate sobre los artículos del dict comprobando si la clave existe y si no - crear un valor vacío -

        for i in transaction_Values_rules.values():
        if 'ref_by_month' in i:
            pass
        else:
            i['ref_by_month'] = '0'
    

    Respondida el Dec 16, 2020 a las 11:52 - por hackharbinger

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando se debe a que estás intentando combinar dos querysets de diferente longitud en un solo gráfico, lo que causa desajustes en las fechas y valores correspondientes. Para resolver esto, puedes ajustar tus querysets para que tengan la misma longitud antes de renderizar el gráfico en Chart.js.

    Aquí te dejo una posible solución para que puedas lograr una representación correcta en el gráfico:

    • Ajusta tus querysets para que tengan la misma longitud, completando con ceros los valores faltantes en el queryset más corto. Esto garantizará que tengas las mismas fechas y valores en ambos sets de datos.
    • Utiliza una función en Python para completar con ceros los valores faltantes en los querysets antes de renderizar el gráfico.

    Aquí te muestro cómo podrías hacerlo:

    python
    

    Asegurarse que ambos querysets tengan la misma longitud

    max_length = max(len(aggregatedSales), len(aggregatedRefunds)) for qs in [aggregatedSales, aggregatedRefunds]: if len(qs) < max_length: for i in range(max_length - len(qs)): qs.append({ 'transactiondate': None, 'sales_by_month': 0, 'ref_by_month': 0 })

    Renderizar el gráfico en el template

    labels = [] sales_data = [] refunds_data = [] for sale, refund in zip(aggregatedSales, aggregatedRefunds): labels.append(sale['transactiondate']) sales_data.append(sale['sales_by_month']) refunds_data.append(refund['ref_by_month'])

    Luego en el template, puedes usar las variables labels, sales_data y refunds_data para renderizar el gráfico en Chart.js

    Con este enfoque, estarás asegurando que tanto las fechas como los valores están alineados correctamente en ambos querysets, lo que evitará la falta de coincidencia en el gráfico. Espero que esta solución te sea de ayuda.

    Respondida el Dec 17, 2020 a las 11:50 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Problema:

    Estás intentando fusionar querysets de Django de diferentes tamaños, lo que provoca un desajuste de fechas en tu gráfico. Esto se debe a que los querysets están devolviendo diferentes tamaños debido a que algunas fechas no coinciden con el filtro aplicado.

    Solución:

    Una forma de abordar este problema es utilizar la anotación Coalesce para combinar los valores de los querysets. Coalesce devuelve el primer valor no nulo de una lista de expresiones.

    Código actualizado:

    python
    from django.db.models import Coalesce
    
    aggregatedSales = Transactionlog.objects.using('database').filter(
        transactiondate__gte=six_month_previous_date).filter(
        transactiontype=1).values('transactiondate').annotate(
        sales_by_month=Coalesce('sales_by_month', 0))
    
    aggregatedRefunds = Transactionlog.objects.using('database').filter(
        transactiondate__gte=six_month_previous_date).exclude(
        transactiontype=1).values('transactiondate').annotate(
        ref_by_month=Coalesce('ref_by_month', 0))
    
    transaction_Values_list = list(chain(aggregatedRefunds, aggregatedSales ))
    
    transaction_Values_rules = defaultdict(dict)
    
    for dic in transaction_Values_list:
        transaction_Values_rules[dic['transactiondate']].update(dic)
    

    En el código actualizado, utilizamos Coalesce para reemplazar los valores nulos con 0. Esto garantiza que ambos querysets tengan el mismo tamaño y que los valores de fecha coincidan.

    Nota:

    Esta solución asume que estás utilizando Django 3.2 o superior, ya que Coalesce se introdujo en esa versión. Si estás utilizando una versión anterior de Django, puedes utilizar Case y When para lograr un efecto similar.

    Respondida el Dec 17, 2020 a las 11:55 - por Gemini

    Votos positivos: 0 | Votos negativos: 0