How to calculate cumulative sum with django ORM? - python

I'm trying to group_by() data based on dates and with every day I want to calculate Count on that day also the total count so far.
Sample output I'm getting:
[
{
"dates": "2022-11-07",
"count": 1
},
{
"dates": "2022-11-08",
"count": 3
},
{
"dates": "2022-11-09",
"count": 33
}
]
Sample output I'm trying to achieve:
[
{
"dates": "2022-11-07",
"count": 1,
"cumulative_count": 1
},
{
"dates": "2022-11-08",
"count": 3,
"cumulative_count": 4
},
{
"dates": "2022-11-09",
"count": 33,
"cumulative_count": 37
}
]
Here's my query:
self.serializer_class.Meta.model.objects.all().annotate(dates=TruncDate("date__date")).values("dates").order_by("dates").annotate(count=Count("channel", distinct=True)).values("count", "dates")
How can I extend this query to get a cumulative sum as well?

I tried to solve your problem like this
models.py
class Demo(models.Model):
count =models.IntegerField()
dates = models.DateField()
serializers.py
class DemoSerializer(serializers.ModelSerializer):
class Meta:
model = Demo
fields = "__all__"
Views.py
class DemoAPI(APIView):
def get(self, request, pk=None, format=None):
data = Demo.objects.all()
cumulative_count= 0
# Normal Django ORM Queruset
print('--------- Default Queryset Response ---------')
for i in data:
del i.__dict__['_state']
print(i.__dict__)
# Adding cumulative_count key in ORM Queryset
for i in data:
cumulative_count += i.__dict__['count']
i.__dict__['cumulative_count'] = cumulative_count
# Updated Django ORM Queruset with cumulative_count
print('--------- Updated Queryset Response ---------')
for i in data:
# del i.__dict__['_state']
print(i.__dict__)
Output before delete _state key from Queryset
#--------- Default Queryset Response ---------
{'_state': <django.db.models.base.ModelState object at 0x000001A07002A680>, 'id': 1, 'count': 1, 'dates': datetime.date(2022, 11, 7)}
{'_state': <django.db.models.base.ModelState object at 0x000001A07002A5C0>, 'id': 2, 'count': 3, 'dates': datetime.date(2022, 11, 8)}
{'_state': <django.db.models.base.ModelState object at 0x000001A07002A7A0>, 'id': 3, 'count': 33, 'dates': datetime.date(2022, 11, 9)}
#--------- Updated Queryset Response ---------
{'_state': <django.db.models.base.ModelState object at 0x000002DAB66E0AC0>, 'id': 1, 'count': 1, 'dates': datetime.date(2022, 11, 7), 'cumulative_count': 1}
{'_state': <django.db.models.base.ModelState object at 0x000002DAB66E0C10>, 'id': 2, 'count': 3, 'dates': datetime.date(2022, 11, 8), 'cumulative_count': 4}
{'_state': <django.db.models.base.ModelState object at 0x000002DAB66E0D60>, 'id': 3, 'count': 33, 'dates': datetime.date(2022, 11, 9), 'cumulative_count': 37}
Output after delete _state key from Queryset Added cumulative_count key in Queryset
#--------- Default Queryset Response ---------
{'id': 1, 'count': 1, 'dates': datetime.date(2022, 11, 7)}
{'id': 2, 'count': 3, 'dates': datetime.date(2022, 11, 8)}
{'id': 3, 'count': 33, 'dates': datetime.date(2022, 11, 9)}
#--------- Updated Queryset Response ---------
{'id': 1, 'count': 1, 'dates': datetime.date(2022, 11, 7), 'cumulative_count': 1}
{'id': 2, 'count': 3, 'dates': datetime.date(2022, 11, 8), 'cumulative_count': 4}
{'id': 3, 'count': 33, 'dates': datetime.date(2022, 11, 9), 'cumulative_count': 37}

Related

Django group by month with possible zeros

Am creating an chart for data analytics. So i need to group the count by month for the whole year.
My model:
Class Application:
reference,
created_at
From the above, i need count of applications for each month for the current year. And with the current query i get all the data but i am not getting data for the months which no data is available:
My query:
queryset = Application.objects.filter(user=user).annotate(month=TruncMonth('created_at')).values('month').annotate(_applications=Count('id')).order_by('month')
For example, If i have data for month Jan and Feb the above query gives data of those only but i need the data to contain "0" for all non data available months:
If March doesnt have data means, the result should be "0" for that month. How to do this ?
You can manually create your dataset using query reqults
queryset = Application.objects.filter(user=user).annotate(
month=TruncMonth('created_at')).values('month').annotate(
_applications=Count('id')).order_by('month')
applications_by_month = {
m['month'].month: m['_applications'] for m in queryset
}
dataset = []
year = 2021
for month in range(1, 13):
dataset.append({
"month": datetime.date(year=year, month=month, day=1),
"applications": applications_by_month.get(month, 0)
})
print(dataset)
Output
[{'month': datetime.date(2021, 1, 1), 'applications': 0},
{'month': datetime.date(2021, 2, 1), 'applications': 0},
{'month': datetime.date(2021, 3, 1), 'applications': 1},
{'month': datetime.date(2021, 4, 1), 'applications': 0},
{'month': datetime.date(2021, 5, 1), 'applications': 0},
{'month': datetime.date(2021, 6, 1), 'applications': 1},
{'month': datetime.date(2021, 7, 1), 'applications': 0},
{'month': datetime.date(2021, 8, 1), 'applications': 0},
{'month': datetime.date(2021, 9, 1), 'applications': 0},
{'month': datetime.date(2021, 10, 1), 'applications': 0},
{'month': datetime.date(2021, 11, 1), 'applications': 0},
{'month': datetime.date(2021, 12, 1), 'applications': 0}]

How can I apply groupby on django queryset

I have a queryset say,
a_query = <QuerySet [{'id': 1, 'user_id': 10, 'name': 'xyz'}, {'id': 2, 'user_id': 10, 'name': 'abc'},{'id': 3, 'user_id': 12, 'name': 'pqr'}]>
So here I want to apply groupby on user_id so the result should be,
[(10, [['xyz', 1], ['abc', 2]]), (12, ['pqr', 1])]
I tried using itemgetter and groupby but that doesn't work.

How to get current user's properties into dict format [duplicate]

This question already has answers here:
Convert Django Model object to dict with all of the fields intact
(17 answers)
Closed 3 years ago.
How to get current user's properties into dict format like given below... I tried request.user.__dict__ and request.user.__class__.__dict__ but not giving that data
{
'_state': < django.db.models.base.ModelState object at 0x7fa2c8a14da0 > ,
'id': 1,
'password': 'gVFDqqWHxJhnrkyYANJb',
'last_login': None,
'is_superuser': False,
'username': 'ualexander',
'first_name': 'Valerie',
'last_name': 'Jones',
'email': 'gonen#yahoo.com',
'is_staff': False,
'is_active': True,
'date_joined': datetime.datetime(2019, 4, 6, 10, 52, 24, 142211, tzinfo = < UTC > )
}
views.py
def dashboard_view(request):
print(request.user.__dict__)
my output
{'_setupfunc': <function AuthenticationMiddleware.process_request.<locals>.<lambda> at 0x7fe71c6bfea0>, '_wrapped': <User: nitin>}
You can do this.
request.user.__class__.objects.filter(pk=request.user.id).values().first()
It will return sample output like this
{'id': 1, 'last_login': datetime.datetime(2019, 4, 5, 10, 44, 19, 110212, tzinfo=<UTC>), 'is_superuser': True, 'username': 'example', 'first_name': 'first', 'last_name': 'last', 'is_staff': True, 'is_active': True, 'date_joined': datetime.datetime(2019, 4, 5, 9, 31, 16, 736841, tzinfo=<UTC>), 'created_at': datetime.datetime(2019, 4, 5, 9, 31, 16, 962971, tzinfo=<UTC>), 'modified_at': datetime.datetime(2019, 4, 5, 9, 31, 16, 962992, tzinfo=<UTC>), 'deleted_at': None, 'is_deleted': False, 'user_id': 1, 'password': 'pbkdf2_sha256$150000$JDcvyHbn1aFI$8gzgVZP/+bvZVQ/OISSF/+BJcJuAJE7zGU4rpBVpA8M=', 'email': 'examle#gmail.com', 'member_from': datetime.date(2019, 1, 1), 'phone_number': '011111111'}
Update:
You want to get objects as dictionary for request user.
In django request.user not give you data as dict format
To get your desired result, You need to do some tricky task.
request.user.__class__.objects.filter(pk=request.user.id).values().first()
here request.user.__class__ is result the model name, then filter this with current user.

Sort list of Dict By Multiple Keys, Including List

I would like to sort this list of dicts by a list key and then by date.
I am trying to sort the dicts by 'label' according the label_order and then by descending 'date'.
label_order = [3, 4, 2, 1]
data = [
{'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
{'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
{'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
{'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
{'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
]
After sorting would look like this:
data = [
{'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
{'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
{'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
{'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
{'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
]
I've tried lambda expressions and itemgetter, but I am having difficulty combining the right strategies for the sort key. Maybe it is just trying to do too much at one time.
Any help or direction would be appreciated.
A more efficient approach is to build a dict that maps items in label_order to indices, so that you can use the indices as keys when performing the sort:
keys = {n: i for i, n in enumerate(label_order)}
sorted(data, key=lambda d: (-keys[d['label']], d['date']), reverse=True)
This returns:
[{'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
{'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
{'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
{'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
{'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)}]
It's a little tricky to sort dates in reverse order. Instead, let's use the negative of the label's index so they're sorted in descending order. Then we can reverse the sorting and get the results in the order we actually want!
from datetime import datetime
label_order = [3, 4, 2, 1]
data = [
{'label': 1, 'data': 5, 'date': datetime(2018, 12, 31)},
{'label': 3, 'data': 2, 'date': datetime(2017, 12, 31)},
{'label': 3, 'data': 1, 'date': datetime(2018, 12, 31)},
{'label': 4, 'data': 3, 'date': datetime(2018, 12, 31)},
{'label': 4, 'data': 4, 'date': datetime(2018, 12, 25)},
]
def descending_sort_key(item):
return -label_order.index(item['label']), item['date']
data.sort(key=descending_sort_key, reverse=True)
Voila - no date math or other trickery.

Add String to list items and then create a dict in python

I have two list and i would like to create dict with each list where key value is a string and then combine those two dicts in one, below are my list :
list_1 : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
list_2 : ['BACKUP_INFO', 'sqlite_sequence', 'BACKUP_INFO_SEARCH', 'BACKUP_INFO_SEARCH_content', 'BACKUP_INFO_SEARCH_segments', 'BACKUP_INFO_SEARCH_segdir', 'BACKUP_INFO_SEARCH_docsize', 'BACKUP_INFO_SEARCH_stat', 'FILE_INFO', 'FILE_INFO_SEARCH', 'FILE_INFO_SEARCH_content', 'FILE_INFO_SEARCH_segments', 'FILE_INFO_SEARCH_segdir', 'FILE_INFO_SEARCH_docsize', 'FILE_INFO_SEARCH_stat']
List_1 should be added with dict key value as 'id'
List_2 should be added with dict key value as 'table'
Then, both the above dicts should be combined into one dict to form something similar to this :
{
"output":
{
"id": 1,
"table" : BACKUP_INFO
}
{
"id": 2,
"table" :sqlite_sequence
}
}
But, i am getting the below output using
table_list_out = dict(zip(list_1, list_2))
return { 'output' : {'id' : list_1, 'table_name' : list_2}}:
{
"output": {
"id": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15
],
"table_name": {
"1": "BACKUP_INFO",
"2": "sqlite_sequence",
"3": "BACKUP_INFO_SEARCH",
"4": "BACKUP_INFO_SEARCH_content",
"5": "BACKUP_INFO_SEARCH_segments",
"6": "BACKUP_INFO_SEARCH_segdir",
"7": "BACKUP_INFO_SEARCH_docsize",
"8": "BACKUP_INFO_SEARCH_stat",
"9": "FILE_INFO",
"10": "FILE_INFO_SEARCH",
"11": "FILE_INFO_SEARCH_content",
"12": "FILE_INFO_SEARCH_segments",
"13": "FILE_INFO_SEARCH_segdir",
"14": "FILE_INFO_SEARCH_docsize",
"15": "FILE_INFO_SEARCH_stat"
}
}
}
You can use a list comprehension:
list_1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
list_2 = ['BACKUP_INFO', 'sqlite_sequence', 'BACKUP_INFO_SEARCH', 'BACKUP_INFO_SEARCH_content', 'BACKUP_INFO_SEARCH_segments', 'BACKUP_INFO_SEARCH_segdir', 'BACKUP_INFO_SEARCH_docsize', 'BACKUP_INFO_SEARCH_stat', 'FILE_INFO', 'FILE_INFO_SEARCH', 'FILE_INFO_SEARCH_content', 'FILE_INFO_SEARCH_segments', 'FILE_INFO_SEARCH_segdir', 'FILE_INFO_SEARCH_docsize', 'FILE_INFO_SEARCH_stat']
new_dict = {'output':[{'id':a, 'table':b} for a, b in zip(list_1, list_2)]}
Output:
{'output': [{'table': 'BACKUP_INFO', 'id': 1}, {'table': 'sqlite_sequence', 'id': 2}, {'table': 'BACKUP_INFO_SEARCH', 'id': 3}, {'table': 'BACKUP_INFO_SEARCH_content', 'id': 4}, {'table': 'BACKUP_INFO_SEARCH_segments', 'id': 5}, {'table': 'BACKUP_INFO_SEARCH_segdir', 'id': 6}, {'table': 'BACKUP_INFO_SEARCH_docsize', 'id': 7}, {'table': 'BACKUP_INFO_SEARCH_stat', 'id': 8}, {'table': 'FILE_INFO', 'id': 9}, {'table': 'FILE_INFO_SEARCH', 'id': 10}, {'table': 'FILE_INFO_SEARCH_content', 'id': 11}, {'table': 'FILE_INFO_SEARCH_segments', 'id': 12}, {'table': 'FILE_INFO_SEARCH_segdir', 'id': 13}, {'table': 'FILE_INFO_SEARCH_docsize', 'id': 14}, {'table': 'FILE_INFO_SEARCH_stat', 'id': 15}]}
From the looks of things, your desired output is impossible. Notice that there are multiple values corresponding to the key: "output".
What is possible is something like this, where the value corresponding to 'output' is a list of dictionaries.
return {'output': [{'id': x, 'table': y} for x, y in zip(list1, list2)]}
You can just loop through it, I'm sure there's a one-liner but this is rather clear.
output = {"output":{} }
for i in xrange(0, len(list_1)):
output["output"][list_2[i]] = list_1[i]
print output

Categories

Resources