2

I have this one model where I have fetch published count , under process count, rejected count, received count on monthly basis

class PreData(models.Model):

    status=models.CharField(max_length=200,default=None,null=True)

    receivedon=models.DateField(default=None,blank=False,null=True)

    publishedon = models.DateField(default=None, blank=True, null=True)

received count is based on monthly count of receivedon DateField in model, published count is based on monthly count of publishedon DateField in model, rejected count and under process count is based on count of specific status value of CharField in model.

I'm struggling after writing below queries,I'm clueless as to how fetch data to fill the columns(see figure). I'm not sure queries I wrote will help.

The problem comes when I want to zip received_monthly_data and published_monthly_data but received_monthly_data has data from April month and published_monthly_data didn't have April month. when i zip , results will loose April month. I am not able to figure how to do this.

received_monthly_data = PreData.objects.filter(journaluser=request.user.username).\
                annotate(month=TruncMonth('receivedon'),year=TruncYear('receivedon')).values('month','year').\
                annotate(c=Count('id')).order_by('-month')

published_monthly_data = PreData.objects.filter(Q(journaluser=request.user.username)&~Q(pdfsenton=None)). \
                annotate(month=TruncMonth('publishedon'), year=TruncYear('publishedon')).values('month', 'year'). \
                annotate(c=Count('id')).order_by('-month')


underproc_data= PreData.objects.filter(Q(journaluser=request.user.username)&~Q(status="[Published]"))

I need the data to fill these columns

Any help is highly appreciated.

joelvarma
  • 150
  • 3
  • 17

1 Answers1

2

Perhaps you could use itertools.zip_longest which will zip the longest sequence and will substitute None for the missing values in the shorter sequence. That way you won't lose the April data.

If you wish to use a value other than None, specify the fillvalue argument.

From https://docs.python.org/3/library/itertools.html#itertools.zip_longest

itertools.zip_longest(*iterables, fillvalue=None)

Make an iterator that aggregates elements from each of the iterables. If the iterables are of uneven length, missing values are filled-in with fillvalue. Iteration continues until the longest iterable is exhausted.

Note that the function is called itertools.izip_longest in Python 2.

Will Keeling
  • 22,055
  • 4
  • 51
  • 61
  • That Worked! Thank you very much @Will Keeling. – joelvarma Apr 23 '18 at 11:10
  • How do I access `fillvalue` arguments value in django templates? – joelvarma Apr 24 '18 at 06:18
  • It would be better to perform the zip in the view before handing the resulting list of data to the template. That way you wouldn't have to deal with the `fillvalue` in the template itself. – Will Keeling Apr 24 '18 at 08:00
  • Yea I have done it the same way, however I couldn't get solution to my problem as zipping and iterating in template is making lot of for loop iterations in template and there's also other problem. So I kinda wanted to know if I can write my own dictionary to populate with only fields I wanted by iterating for loop for like 100 times in view it self? Will this be good? – joelvarma Apr 25 '18 at 13:12
  • Yes that sounds like a reasonable approach. It is always a good idea to keep the logic in the template simple by preprocessing the data in the view. – Will Keeling Apr 25 '18 at 14:05
  • Oh great then, Thank you very much for suggestion! :) – joelvarma Apr 25 '18 at 18:27