Django Annotate with one model and include "annotated" records in queryset - django

I am fairly new to Django and have figured out the "basic" annotate function, but I would like to include the records from the annotated values. For example,
qs = People.objects.values('status').annotate(total=Count('id'),totalScore=Sum('score'),averageAge=Avg('age'))
I would like to include the summarized records in the result, in this case the individual people, like so...
[
{'status': 'One',
'total': 2,
'totalScore': 150,
'averageAge': 36,
'people': [
{
'id': 1,
'status': 'One',
'name': 'Jim',
'score': 80,
'age': 40
},
{
'id': 5,
'status': 'One',
'name': 'Jill',
'score': 70,
'age': 32
}
]},
{'status': 'Two',
'total': 1,
'totalScore': 85,
'averageAge': 42,
'people': [
{
'id': 3,
'status': 'Two',
'name': 'Jack',
'score': 85,
'age': 42
}
]
},...
Thanks for any help.

Related

How does Django query the tree structure

I am new to Django and I am creating a blog and comment function
from django.db import models
from django.contrib.auth import get_user_model
class Blog(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
title = models.CharField(max_length=200)
content = models.TextField(max_length=200)
class Comment(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name="children")
content = models.CharField(max_length=200)
This is my current test data
Comment.objects.all().values()
<QuerySet [
{'id': 1, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '1'},
{'id': 2, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '2'},
{'id': 3, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '1-1'},
{'id': 4, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '1-2'}
]>
But now I want to find out such a tree structure, what should I do?
[
{'id': 1, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '1', 'children': [
{'id': 3, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '1-1'},
{'id': 4, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '1-2'}
]},
{'id': 2, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '2', 'children': [] },
]
You can' t obtain a nested dictionary with values.
You could write this:
Comment.objects.all().values('id', 'user_id', 'blog_id', 'parent_id', 'content', 'children')
But the result will not be as you expected, the list will contain a dict for every parent-child combination, for example:
[
{'id': 1, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '1', children: 2},
{'id': 1, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '1', children: 3},
{'id': 2, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '2', children: None},
{'id': 3, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '2', children: None},
]
You can deal directly with the queryset, for example:
for comment in Comment.objects.all().prefetch_related('children'):
for child in comment.children.all():
print(child.id)
Or you can use a nested list comprehension (the result will be as you expected):
print([{'id': comment.id, 'user_id': comment.user.id, 'blog_id': comment.blog.id, 'parent_id': comment.parent.id if comment.parent != None else None, 'content': comment.content, 'children': [{'id':
child.id, 'user_id': child.user.id, 'blog_id': child.blog.id, 'parent_id': child.parent.id, 'content': child.content} for child in comment.children.all()]} for comment in Comment.objects.all()])
I use recursion to query
def get_children(c):
return {
'id': c.id,
'user_id': c.user_id,
'blog_id': c.blog_id,
'parent_id': c.parent_id,
'content': c.content,
'children': list(map(get_children, c.children.all())),
}
def get_comment_tree():
return list(map(get_children, Comment.objects.filter(parent=None).prefetch_related('children')))
Output json
[{
"id": 1,
"user_id": 1,
"blog_id": 1,
"parent_id": null,
"content": "1",
"children": [{
"id": 3,
"user_id": 1,
"blog_id": 1,
"parent_id": 1,
"content": "1-1",
"children": [{
"id": 5,
"user_id": 1,
"blog_id": 1,
"parent_id": 3,
"content": "1-1-1",
"children": []
}]
}, {
"id": 4,
"user_id": 1,
"blog_id": 1,
"parent_id": 1,
"content": "1-2",
"children": []
}]
}, {
"id": 2,
"user_id": 1,
"blog_id": 1,
"parent_id": null,
"content": "2",
"children": []
}]

Dart maps, how to replace specific key value in a list<map> based on its key id?

void main() {
List<Map<String, dynamic>> products = [
{'id': 24, 'time': '2019-11-24 00:00:00.000'},
{'id': 36, 'time': '2019-11-23 00:00:00.000'},
{'id': 48, 'time': '2019-11-24 00:00:00.000'},
];
In the code above I want to replace 'time' entry '2019-11-24 00:00:00.000' to '2019-10-26 00:00:00.000' for the 'id' 48.
You can try something like this:
products.where((x) => x["id"] == 48).first["time"] = "2019-10-26 00:00:00.000";
Here is another way how you can do it:
void main() {
List<Map<String, dynamic>> products = [
{'id': 24, 'time': '2019-11-24 00:00:00.000'},
{'id': 36, 'time': '2019-11-23 00:00:00.000'},
{'id': 48, 'time': '2019-11-24 00:00:00.000'},
];
products = products.map((product){
if(product["id"] == 48){
return {...product, 'time': '2019-10-26 00:00:00.000'};
}
return product;
}).toList();
print(products.toString());
}

Dart/Flutter - How to delete key-value-pairs of element of Map inside a List?

How can I can delete a specific key-value-pair in that type of List<Map<String, dynamic>> for each map.
For example:
List<Map<String, dynamic>> before the operation:
List<Map<String, dynamic>> currencies = [
{
'id': 1,
'name': 'coin',
'desc': 'This is just a blindtext.',
'order': 101,
'icon': 'https://icon1.jpg'
},
{
'id': 2,
'name': 'karma',
'desc': 'This is just a blindtext.',
'order': 102,
'icon': 'https://icon2.jpg'
},
{
'id': 3,
'name': 'laurel',
'desc': 'This is just a blindtext.',
'order': 104,
'icon': 'https://icon3.jpg'
},
];
List<Map<String, dynamic>> after the operation I am searching for:
List<Map<String, dynamic>> currencies = [
{
'id': 1,
'name': 'coin',
'icon': 'https://icon1.jpg'
},
{
'id': 2,
'name': 'karma',
'icon': 'https://icon2.jpg'
},
{
'id': 3,
'name': 'laurel',
'icon': 'https://icon3.jpg'
},
];
So basically, I deleted "unwanted" key-value-pairs.
Any suggestions?
Thanks in advance!!
currencies.forEach((item) => item..remove("order")..remove("desc"));

how to count number of occurrences of element in list of maps in dart?

I have a list of maps like this
data = [
{
'id': 100,
'quantity': 20
},
{
'id': 101,
'quantity': 25
},
{
'id': 101,
'quantity': 30
}
{
'id': 105,
'quantity': 50
}
]
I am able to count occurrences of element in a list like this
data.forEach((x) => map[x] = !map.containsValue(x) ? (1) : (map[x] + 1));
print(map);
Output :
{{id: 100, quantity: 20}: 1, {id: 101, quantity: 25}: 1, {id: 101, quantity: 30}: 1, {id: 105, quantity: 50}: 1}
But I want to count how many times id = 101 comes in the list so How can I achieve that?
You can use where to filter your array of maps and then use the getter length :
var data = [
{'id': 100, 'quantity': 20},
{'id': 101, 'quantity': 25},
{'id': 101, 'quantity': 30},
{'id': 105, 'quantity': 50}
];
print(data.where((e) => e['id'] == 101).length); // 2

How to create an element using values of already existed elements in a dict, inside a list?

Here is my example:
print (stock_info)
>>> [{'symbol': 'AAPL', 'name': 'Apple Inc.', 'price': 145.16, 'quantity': 20}, {'symbol': 'AMZN', 'name': 'Amazon.com, Inc.', 'price': 998.61, 'quantity': 20}, {'symbol': 'FB', 'name': 'Facebook, Inc.', 'price': 152.96, 'quantity': 30}, {'symbol': 'GOOG', 'name': 'Alphabet Inc.', 'price': 957.01, 'quantity': 20}]
I have 'price' and 'quantity' fields with values.
And now I would like to create a field called 'total' = price * quantity
How to create a new field ('total': value) based on values of 2 fields, which already exist ( value = price * quantity)?
As a result I want to see:
>>> [{'symbol': 'AAPL', 'name': 'Apple Inc.', 'price': 145.16, 'quantity': 20, 'total' : 2903.2}, {'symbol': 'AMZN', 'name': 'Amazon.com, Inc.', 'price': 998.61, 'quantity': 20, 'total' : 19972.2}, {'symbol': 'FB', 'name': 'Facebook, Inc.', 'price': 152.96, 'quantity': 30, 'total' : 4588.8}, {'symbol': 'GOOG', 'name': 'Alphabet Inc.', 'price': 957.01, 'quantity': 20, 'total' : 19140.2}]
So each dict (dict, yes?) was extended with a new field 'total' and its value.
How to implement this idea?
Any help is greatly appreciated ;)
Thanks!
Just loop through your data and add a new key to your dictionaries:
for stock_item in stock_info:
stock_item["total"] = stock_item["price"] * stock_item["quantity"]
EDIT - Testing with your data:
stock_info = [{'symbol': 'AAPL', 'name': 'Apple Inc.', 'price': 145.16, 'quantity': 20},
{'symbol': 'AMZN', 'name': 'Amazon.com, Inc.', 'price': 998.61, 'quantity':20},
{'symbol': 'FB', 'name': 'Facebook, Inc.', 'price': 152.96, 'quantity': 30},
{'symbol': 'GOOG', 'name': 'Alphabet Inc.', 'price': 957.01, 'quantity': 20}]
for stock_item in stock_info:
stock_item["total"] = stock_item["price"] * stock_item["quantity"]
print(stock_info)
yields:
[{'name': 'Apple Inc.', 'price': 145.16, 'symbol': 'AAPL', 'total': 2903.2, 'quantity': 20},
{'name': 'Amazon.com, Inc.', 'price': 998.61, 'symbol': 'AMZN', 'total': 19972.2, 'quantity': 20},
{'name': 'Facebook, Inc.', 'price': 152.96, 'symbol': 'FB', 'total': 4588.8, 'quantity': 30},
{'name': 'Alphabet Inc.', 'price': 957.01, 'symbol': 'GOOG', 'total': 19140.2, 'quantity': 20}]