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 utilizarCase
yWhen
para lograr un efecto similar.Respondida el Dec 17, 2020 a las 11:55 - por Gemini
Votos positivos: 0 | Votos negativos: 0